摘要:除非文件用自帶的記事本打開我們能夠讀懂,才采用字符流,否則建議使用字節(jié)流。
第四階段 IO IO流 前言:
前面的學(xué)習(xí)我們只能夠在已有的一定封閉范圍內(nèi)進(jìn)行一些操作,但是這顯然是無趣的,也是不支持我們實(shí)現(xiàn)一些復(fù)雜的需求,所以Java提供IO流這樣一種概念,方便我們對(duì)數(shù)據(jù)進(jìn)行操作
而使用IO流我們可以實(shí)現(xiàn)一些強(qiáng)大的功能,例如針對(duì)文件的移動(dòng)復(fù)制等操作,又或者程序與外部文件之間的數(shù)據(jù)存儲(chǔ)或者讀取,又或者實(shí)現(xiàn)一個(gè)實(shí)時(shí)的聊天程序(網(wǎng)絡(luò)編程),其中數(shù)據(jù)的傳輸也用到了我們的IO流,這些內(nèi)容我們都會(huì)在后面設(shè)計(jì),下面我就開始IO流的正式學(xué)習(xí)
(一) IO流的概述及分類 (1) 概念IO 即 input/output(輸入/輸出),流的概念還是有一些陌生的
“流”從字面看來就是類似水流的概念,其具有方向性,流動(dòng)性,連續(xù)性、并且可以承載一些事物,而在我們計(jì)算機(jī)中,“流”是對(duì)一種有序連續(xù)具有方向性的數(shù)據(jù)的抽象描述。其本質(zhì)就是數(shù)據(jù)的傳輸,而根據(jù)其特點(diǎn)將其抽象封裝為各種類,更加方便了用戶的操作
(2) 分類A:流向
輸入流——讀取數(shù)據(jù)
輸出流——寫出數(shù)據(jù)
B:數(shù)據(jù)類型
字節(jié)流
字節(jié)輸入流——InputStream
字節(jié)輸出流——OutputStream
字符流
字符輸入流——Reader
字符輸出流——Writer
注意:
a: 如果我們沒有明確說明按照什么分,默認(rèn)按照數(shù)據(jù)類型分。
b: 除非文件用windows自帶的記事本打開我們能夠讀懂,才采用字符流,否則建議使用字節(jié)流。
(二) 字節(jié)流 (1) FileOutputStream 寫出數(shù)據(jù)A:操作步驟
創(chuàng)建字節(jié)輸出流對(duì)象
調(diào)用writer()方法
釋放資源
B:代碼體現(xiàn)
FileOutputStream fos = new FileOutputStream("fos.txt"); for.write("hello".getBytes()); fos.close;
換行操作
因?yàn)椴煌南到y(tǒng)針對(duì)不同的換行符號(hào)識(shí)別是不一樣的
windows:rn linux:n Mac:r
而一些常見的高級(jí)記事本是可以識(shí)別任意換行符號(hào)的
如何實(shí)現(xiàn)數(shù)據(jù)的追加寫入 ?
用構(gòu)造方法帶第二個(gè)參數(shù)是true的情況即可
FileOutputStream?fos?=?new?FileOutputStream("fos.txt",?true);(2) FileInputStream 讀取數(shù)據(jù)
A:操作步驟
創(chuàng)建字節(jié)輸入流對(duì)象
調(diào)用writer()方法
釋放資源
B:代碼體現(xiàn)
FileInputStream fis = new FileInputStream("fos.txt");
//使用FileInputStream對(duì)指定路徑下內(nèi)容進(jìn)行讀取,可以結(jié)合FileOutputStream實(shí)現(xiàn)對(duì)文件的操作 import java.io.FileInputStream; import java.io.IOException; public class FileInputStreamDemo { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("F:fos.txt"); //方式一 int by = 0; while ((by = fis.read()) != -1){ System.out.print((char)by); } //方式二(這種方式更加快,推薦) //數(shù)組長度一般是1024或者1024的整數(shù)倍 byte[] bys = new byte[1024]; int len = 0; while((len = fis.read(bys))!=-1){ System.out.print(new String(bys,0,len)); } //釋放資源 fis.close(); } }(3) 字節(jié)緩沖流
//統(tǒng)計(jì)這段程序運(yùn)行時(shí)間 long start = System.currentTimeMillis(); //受測試代碼 long end = System.currentTimeMillis(); System.out.println("共耗時(shí)" + (end - start) + "毫秒");
字節(jié)流一次讀寫一個(gè)數(shù)組的速度明顯比一次讀寫一個(gè)字節(jié)的速度快很多,這是加入了數(shù)組這樣的緩沖區(qū)效果,java本身在設(shè)計(jì)的時(shí)候,也考慮到了這樣的設(shè)計(jì)思想(裝飾設(shè)計(jì)模式后面講解),所以提供了字節(jié)緩沖區(qū)流
//字節(jié)緩沖輸出流 BuffereOutputStream //字節(jié)緩沖輸入流 BufferedInputStream
import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; public class BufferedOutputStreamDemo { public static void main(String[] args) throws IOException { // FileOutputStream fos = new FileOutputStream("F:fos.txt"); // BufferedOutputStream bos = new BufferedOutputStream(fos); //簡單寫法 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:fos.txt")); //寫數(shù)據(jù) bos.write("hello".getBytes()); //釋放資源,注意不需要fos.close bos.close(); } }
為什么不傳遞一個(gè)具體的文件或者文件路徑,而是傳遞一個(gè)OutputStream對(duì)象呢?
原因很簡單,字節(jié)緩沖區(qū)流僅僅提供緩沖區(qū),為高效而設(shè)計(jì)的。但是呢,真正的讀寫操作還得靠基本的流對(duì)象實(shí)現(xiàn)。
import java.io.*; public class Test { public static void main(String[] args) throws IOException { long start = System.currentTimeMillis(); method1("E:夜曲.mp3", "F:Test1.mp3"); method2("E:夜曲.mp3", "F:Test2.mp3"); method3("E:夜曲.mp3", "F:Test3.mp3"); method4("E:夜曲.mp3", "F:Test4.mp3"); long end = System.currentTimeMillis(); System.out.println("共耗時(shí)" + (end - start) + "毫秒"); } //基本字節(jié)流一次讀寫一個(gè)字符 public static void method1(String srcString, String deskString) throws IOException { FileInputStream fis = new FileInputStream(srcString); FileOutputStream fos = new FileOutputStream(deskString); int by = 0; while ((by = fis.read()) != -1) { fos.write(by); } fis.close(); fos.close(); } //基本字節(jié)流一次讀寫一個(gè)字節(jié)數(shù)組 public static void method2(String srcString, String deskString) throws IOException { FileInputStream fis = new FileInputStream(srcString); FileOutputStream fos = new FileOutputStream(deskString); byte[] bys = new byte[1024]; int len = 0; while ((len = fis.read(bys)) != -1) { fos.write(bys, 0, len); } fis.close(); fos.close(); } //高效字節(jié)流一次讀寫一個(gè)字節(jié) public static void method3(String srcString, String deskString) throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcString)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(deskString)); int by = 0; while ((by = bis.read()) != -1) { bos.write(by); } bis.close(); bos.close(); } //高效字節(jié)流一次讀寫一個(gè)字節(jié)數(shù)組 public static void method4(String srcString, String deskString) throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcString)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(deskString)); byte[] bys = new byte[1024]; int len = 0; while ((len = bis.read(bys)) != -1) { bos.write(bys, 0, len); } } } //運(yùn)行結(jié)果 共耗時(shí)125961毫秒 共耗時(shí)143毫秒 共耗時(shí)1356毫秒 共耗時(shí)29毫秒
由此可見在上述四種方式中,效率最高的還是最后一種——高效字節(jié)流一次讀寫一個(gè)字節(jié)數(shù)組!
(三) 字符流我們?cè)陂_發(fā)中,如果想要對(duì)我們所能識(shí)別的文本內(nèi)容進(jìn)行數(shù)據(jù)的傳輸,如果我們繼續(xù)使用我們上面所學(xué)習(xí)的字節(jié)流,我們就會(huì)發(fā)現(xiàn)顯示出來的內(nèi)容是亂碼,這是因?yàn)榫幋a出現(xiàn)了問題,而這個(gè)時(shí)候我們就會(huì)用到我們的字符流,我們可以先簡單的認(rèn)識(shí) 字符流 = 字節(jié)流 + 編碼(1) 編碼解碼
編碼 | 說明 |
---|---|
ASCII | 美國標(biāo)準(zhǔn)信息交換碼,用一個(gè)字節(jié)的7位可以表示。 |
ISO8859-1 | 拉丁碼表。歐洲碼表,用一個(gè)字節(jié)的8位表示。 |
GB2312 | 中國的中文編碼表。 |
GBK | 中國的中文編碼表升級(jí),融合了更多的中文文字符號(hào)。 |
GB18030 | GBK的取代版本 |
BIG-5碼 | 行于臺(tái)灣、香港地區(qū)的一個(gè)繁體字編碼方案,俗稱“大五碼”。 |
Unicode | 國際標(biāo)準(zhǔn)碼,融合了多種文字, 有文字都用兩個(gè)字節(jié)來表示,Java語言使用的就是unicode |
UTF-8 | 最多用三個(gè)字節(jié)來表示一個(gè)字符。UTF-8不同,它定義了一種“區(qū)間規(guī)則”,這種規(guī)則可以和ASCII編碼保持最大程度的兼容:它將Unicode編碼為00000000-0000007F的字符,用單個(gè)字節(jié)來表示它將Unicode編碼為00000080-000007FF的字符用兩個(gè)字節(jié)表示 它將Unicode編碼為00000800-0000FFFF的字符用3字節(jié)表示 |
字節(jié)流我們前面已經(jīng)有了一定的認(rèn)識(shí),那么什么是編碼和解碼呢?
編碼是信息從一種形式或格式轉(zhuǎn)換為另一種形式的過程;解碼則是編碼的逆過程。
我們先通過一個(gè)例子來了解一下它的流程
//通過指定的字符集解碼字節(jié)數(shù)組 String(byte[]?bytes,?String?charsetName) //使用指定的字符集合把字符串編碼為字節(jié)數(shù)組 byte[]?getBytes(String?charsetName)
import java.io.UnsupportedEncodingException; import java.util.Arrays; public class EncodingDemo { public static void main(String[] args) throws UnsupportedEncodingException { String s = "理想"; //String - byte[] - 編碼 byte[] bys = s.getBytes(); //[-25, -112, -122, -26, -125, -77] // byte[] bys = s.getBytes("UTF-8"); //[-25, -112, -122, -26, -125, -77] // byte[] bys = s.getBytes("GBK"); //[-64, -19, -49, -21] System.out.println(Arrays.toString(bys)); //byte[] - String - 解碼 String string = new String(bys); //理想 // String string = new String(bys,"UTF-8"); //理想 // String string = new String(bys,"GBK"); //鐞嗘兂 System.out.println(string); } }
發(fā)送過程:“理想” —— 數(shù)字 —— 二進(jìn)制 —— 發(fā)送
接收過程:接收 —— 二進(jìn)制 —— 十進(jìn)制 —— 數(shù)值 —— 字符 —— “理想”
其實(shí)簡單的總結(jié)就是:
編碼:把看得懂的變成看不懂的
解碼:把看不懂的變成看得懂的
(2) 字符輸入輸出流OutputStreamWriter 字符輸出流(寫出)
public OutputStreamWriter(OutputStream out) public OutputStreamWriter(OutputStream out,String charsetName)
InputStreamReader 字符輸入流(讀?。?/strong>
public InputStreamReader(InputStream in) public InputStreamReader(InputStream in,String charsetName)
OutputStreamWriter寫數(shù)據(jù)方法
//寫一個(gè)字符 public void write(int c) //寫一個(gè)字符數(shù)組 public void write(char[] cbuf) //寫一個(gè)字符數(shù)組的一部分 public void write(char[] cbuf,int off,int len) //寫一個(gè)字符串 public void write(String str) //寫一個(gè)字符串的一部分 public void write(String str,int off,int len)
OutputStreamWriter讀數(shù)據(jù)方法
//讀一個(gè)字符 public int read() //第一個(gè)字符數(shù)組 public int read(char[] cbuf)
字符流操作要注意的問題
flush()和close()的區(qū)別 ?
close:關(guān)閉流對(duì)象,但是先刷新一次緩沖區(qū),關(guān)閉之后,流對(duì)象就不能繼續(xù)使用了
flush:僅僅刷新緩沖區(qū),刷新之后,流對(duì)象還可以繼續(xù)使用
(2) 字符流的簡單寫法轉(zhuǎn)換流的名字比較長,而我們常見的操作都是按照本地默認(rèn)編碼實(shí)現(xiàn)的,所以,為了簡化我們的書寫,轉(zhuǎn)換流提供了對(duì)應(yīng)的子類
//輸出流 FileWriter //輸入流 FileReader
OutputStreamWriter?osw?= new?OutputStreamWriter(new?FileOutputStream("b.txt")) //等價(jià) FileWriter?fw?=?new?FileWriter("b.txt"); (寫出) InputStreamReader?isr?=?new?InputStreamReader(new?FileInputStream("a.txt")) //等價(jià)? FileReader?fr?=?new?FileReader("a.txt"); (讀?。?/pre> (3) 字符緩沖流?BufferedWriter:字符緩沖輸出流
將文本寫入字符輸出流,緩沖各個(gè)字符,從而提供單個(gè)字符、數(shù)組和字符串的高效寫入。
可以指定緩沖區(qū)的大小,或者接受默認(rèn)的大小。在大多數(shù)情況下,默認(rèn)值就足夠大了。
BufferedReader:字符緩沖輸入流
從字符輸入流中讀取文本,緩沖各個(gè)字符,從而實(shí)現(xiàn)字符、數(shù)組和行的高效讀取。
可以指定緩沖區(qū)的大小,或者可使用默認(rèn)的大小。大多數(shù)情況下,默認(rèn)值就足夠大了。
特殊功能
BufferedWriter:
//根據(jù)系統(tǒng)來決定換行符 public?void?newLine()BufferedReader:
//一次讀取一行數(shù)據(jù),包含該行內(nèi)容的字符串,不包含任何行終止符,如果已到達(dá)流末尾,則返回?null public?String?readLine()(四) IO流案例 字節(jié)流案例案例一:復(fù)制單級(jí)文件夾
import java.io.*; /* * 需求:復(fù)制單級(jí)文件夾 * * 數(shù)據(jù)源:f:demo * 目的地:f: est * * 分析: * A:封裝目錄 * B:獲取該目錄下的所有文本的File數(shù)組 * C:遍歷該File數(shù)組,得到每一個(gè)File對(duì)象 * D:把該File進(jìn)行復(fù)制 */ public class CopyFolderDemo { public static void main(String[] args) throws IOException { File srcFloder = new File("F:demo"); File deskFloder = new File("F: est"); if (!deskFloder.exists()) { deskFloder.mkdirs(); } File[] fileArray = srcFloder.listFiles(); for (File file : fileArray) { String name = file.getName(); //拼湊出每一個(gè)文件的路徑 File newFile = new File(deskFloder, name); copyFloder(file, newFile); } } public static void copyFloder(File file, File newFile) throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile)); byte[] bys = new byte[1024]; int len = 0; while ((len = bis.read()) != -1) { bos.write(bys, 0, len); } bis.close(); bos.close(); } }案例二:復(fù)制指定目錄下的指定文件,并修改后綴名
import java.io.*; /* * 需求:復(fù)制指定目錄下的指定文件,并修改后綴名。 * 指定的文件是:.txt文件。 * 指定的后綴名是:.bat * 指定的目錄是:test * * 數(shù)據(jù)源:f:demoA.txt * 目的地:f: estA.bat * * 分析: * A:封裝目錄 * B:獲取該目錄下的java文件的File數(shù)組 * C:遍歷該File數(shù)組,得到每一個(gè)File對(duì)象 * D:把該File進(jìn)行復(fù)制 * E:在目的地目錄下改名 */ public class CopyFolderDemo2 { public static void main(String[] args) throws IOException { File srcFloder = new File("F:demo"); File destFloder = new File("F: est"); if (!destFloder.exists()) { destFloder.mkdirs(); } File[] fileArray = srcFloder.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return new File(dir, name).isFile() && name.endsWith(".txt"); } }); for (File file : fileArray) { String name = file.getName(); File newFile = new File(destFloder, name); copyFile(file, newFile); } File[] deskFileArray = destFloder.listFiles(); for (File destFile : deskFileArray) { String name = destFile.getName(); String newName = name.replace(".txt", ".bat"); File newFile = new File(destFloder, newName); destFile.renameTo(newFile); } } public static void copyFile(File file, File newFile) throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile)); byte[] bys = new byte[1024]; int len = 0; while ((len = bis.read(bys)) != -1) { bos.write(bys, 0, len); } bis.close(); bos.close(); } }案例三:復(fù)制多級(jí)文件夾
import java.io.*; /* * 需求:復(fù)制多極文件夾 * * 數(shù)據(jù)源:F:admin * 目的地:E: * * 分析: * A:封裝數(shù)據(jù)源File * B:封裝目的地File * C:判斷該File是文件夾還是文件 * a:是文件夾 * 就在目的地目錄下創(chuàng)建該文件夾 * 獲取該File對(duì)象下的所有文件或者文件夾File對(duì)象 * 遍歷得到每一個(gè)File對(duì)象 * 回到C * b:是文件 * 就復(fù)制(字節(jié)流) */ public class CopyFloderDemo3 { public static void main(String[] args) throws IOException { File srcFile = new File("F:admin"); File destFile = new File("E:"); copyFolder(srcFile, destFile); } private static void copyFolder(File srcFile, File destFile) throws IOException { if (srcFile.isDirectory()) { File newFolder = new File(destFile, srcFile.getName()); newFolder.mkdirs(); //獲取該File對(duì)象下的所有文件或者文件夾File對(duì)象 File[] fileArray = srcFile.listFiles(); for (File file : fileArray) { //遞歸,繼續(xù)判斷 copyFolder(file, newFolder); } } else { File newFile = new File(destFile, srcFile.getName()); copyFile(srcFile, newFile); } } private static void copyFile(File srcFile, File newFile) throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile)); byte[] bys = new byte[1024]; int len = 0; while ((len = bis.read(bys)) != -1) { bos.write(bys, 0, len); } bos.close(); bis.close(); } }字符流案例案例一:隨機(jī)獲取文本文件中的姓名案例
import java.io.*; import java.util.ArrayList; import java.util.Random; /* * 隨機(jī)獲取文本文件中的姓名案例 * 需求:我有一個(gè)文本文件中存儲(chǔ)了幾個(gè)名稱 * 請(qǐng)大家寫一個(gè)程序?qū)崿F(xiàn)隨機(jī)獲取一個(gè)人的名字。 * * 分析: * A:把文本文件中的數(shù)據(jù)存儲(chǔ)到集合中 * B:隨機(jī)產(chǎn)生一個(gè)索引 * C:根據(jù)該索引獲取一個(gè)值 */ public class GetRandName { public static void main(String[] args) throws IOException { String path = "F: est.txt"; // BufferedReader br = new BufferedReader(new FileReader(path)); //默認(rèn)記事本以ansi編碼保存,但是使用FileReader默認(rèn)使用UTF-8輸出,所以使用上面語句會(huì)亂碼 BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path), "gb2312")); ArrayListarray = new ArrayList<>(); String line = null; while ((line = br.readLine()) != null) { array.add(line); } br.close(); Random r = new Random(); int index = r.nextInt(array.size()); String name = array.get(index); System.out.println("該幸運(yùn)兒是:" + name); } } 案例二:鍵盤錄入學(xué)生信息按照總分排序并寫入文本文件案例
//Student類自行補(bǔ)充 import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.util.Comparator; import java.util.Scanner; import java.util.TreeSet; public class StudentDemo { public static void main(String[] args) throws IOException { TreeSetts = new TreeSet (new Comparator () { @Override public int compare(Student s1, Student s2) { int num = s2.getSum() - s1.getSum(); int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num; int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2; int num4 = num3 == 0 ? s1.getEnglish() - s2.getEnglish() : num3; int num5 = num4 == 0 ? s1.getName().compareTo(s2.getName()) : num4; return num5; } }); for (int x = 1; x <= 3; x++) { Scanner sc = new Scanner(System.in); System.out.println("請(qǐng)輸入第" + x + "個(gè)學(xué)生成績信息"); System.out.println("姓名:"); String name = sc.nextLine(); System.out.println("語文成績:"); int chinese = sc.nextInt(); System.out.println("數(shù)學(xué)成績:"); int math = sc.nextInt(); System.out.println("英語成績:"); int english = sc.nextInt(); Student s = new Student(); s.setName(name); s.setChinese(chinese); s.setMath(math); s.setEnglish(english); ts.add(s); BufferedWriter bw = new BufferedWriter(new FileWriter("F:students.txt")); bw.write("學(xué)生成績信息如下"); bw.newLine(); bw.flush(); bw.write("姓名-語文成績-數(shù)學(xué)成績-英語成績"); bw.newLine(); bw.flush(); for (Student stu : ts) { StringBuilder sb = new StringBuilder(); sb.append(stu.getName() + "-" + stu.getChinese() + "-" + stu.getMath() + "-" + stu.getEnglish()); bw.write(sb.toString()); bw.newLine(); bw.flush(); } bw.close(); System.out.println("學(xué)生成績信息錄入完畢"); } } } 案例三:登陸注冊(cè)案例(使用IO)
在前幾篇中集合實(shí)現(xiàn)的基礎(chǔ)上,其余文件不變,只需要對(duì) UserDaoImpl.java 文件進(jìn)行重寫
由于篇幅較長,其余dao、pojo、test層代碼請(qǐng)翻閱前幾篇中 集合框架——List篇
package cn.bwh_05_LoginDemo.dao.impl; import cn.bwh_05_LoginDemo.dao.UserDao; import cn.bwh_05_LoginDemo.pojo.User; import java.io.*; /** * 這是用戶操作的具體實(shí)現(xiàn)類 (IO) * * @author BWH_Steven * @version v1.1 */ public class UserDaoImpl implements UserDao { private static File file = new File("User.txt"); static { try { file.createNewFile(); } catch (IOException e) { System.out.println("創(chuàng)建文件失敗"); e.printStackTrace(); } } @Override public boolean isLogin(String username, String password) { boolean flag = false; BufferedReader br = null; String path = "user.txt"; try { br = new BufferedReader(new FileReader(file)); String line = null; while ((line = br.readLine()) != null) { //用戶名--密碼 String[] datas = line.split("--"); if (datas[0].equals(username) && datas[1].equals(password)) { flag = true; break; } } } catch (FileNotFoundException e) { System.out.println("找不到登錄所需要的信息文件"); e.printStackTrace(); } catch (IOException e) { System.out.println("用戶登錄失敗"); e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { System.out.println("用戶登錄釋放資源失敗"); e.printStackTrace(); } } } return flag; } @Override public void regist(User user) { /* * 為注冊(cè)的數(shù)據(jù)定義一個(gè)規(guī)則: 用戶名--密碼 */ BufferedWriter bw = null; String path = "user.txt"; try { //為了保證數(shù)據(jù)是追加寫入,所以必須加true bw = new BufferedWriter(new FileWriter(file, true)); //bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path,true),"gb2312")); bw.write(user.getUsername() + "--" + user.getPassword()); bw.newLine(); bw.flush(); } catch (IOException e) { System.out.println("用戶注冊(cè)失敗"); e.printStackTrace(); } finally { try { bw.close(); } catch (IOException e) { System.out.println("用戶注冊(cè)釋放資源失敗"); e.printStackTrace(); } } } }結(jié)尾:如果內(nèi)容中有什么不足,或者錯(cuò)誤的地方,歡迎大家給我留言提出意見, 蟹蟹大家 !^_^
如果能幫到你的話,那就來關(guān)注我吧?。ㄏ盗形恼戮鶗?huì)在公眾號(hào)第一時(shí)間更新)
在這里的我們素不相識(shí),卻都在為了自己的夢而努力 ?一個(gè)堅(jiān)持推送原創(chuàng)Java技術(shù)的公眾號(hào):理想二旬不止
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/75327.html
摘要:流做下載等功能時(shí)候,我們經(jīng)常會(huì)使用數(shù)據(jù)流模塊,因?yàn)?,在大文件下載場景下,如果使用接口將文件全部讀入內(nèi)存然后再返回給客戶端,很容易撐爆內(nèi)存,比如一個(gè)文件,同時(shí)有人在下載,那么服務(wù)就需要占用內(nèi)存。 NPM酷庫,每天兩分鐘,了解一個(gè)流行NPM庫。 流 做下載等功能時(shí)候,我們經(jīng)常會(huì)使用數(shù)據(jù)流模塊(stream),因?yàn)椋诖笪募螺d場景下,如果使用fs.readFile()接口將文件全部讀入內(nèi)存...
摘要:本教程將演示通過云直播服務(wù),快速發(fā)起一場支持萬人觀看的直播。一個(gè)完成實(shí)名認(rèn)證的賬號(hào)。體驗(yàn)金到賬后,選擇購買流量,彈框內(nèi)選擇流量包大小,點(diǎn)擊確認(rèn),立即支付,即可完成購買。至此,云直播的配置已經(jīng)完成,下一篇教程指導(dǎo)如何利用工具發(fā)起觀看直播。本教程將演示通過ULive云直播服務(wù),快速發(fā)起一場支持萬人觀看的直播。直播前需要準(zhǔn)備的工具:推流工具OBS 下載地址:測試播放器:下載地址一個(gè)完成ICP備案的...
摘要:選擇網(wǎng)絡(luò),將完整的播放地址粘貼進(jìn)去,點(diǎn)擊串流一直,最后點(diǎn)擊流,即可觀看直播。本教程主要指導(dǎo)大家如何通過快速的發(fā)起一場直播,后續(xù)將為大家介紹視頻轉(zhuǎn)碼截圖錄制存儲(chǔ)等直播中常用增值功能的使用。上文介紹了在UCloud如何配置直播推拉流,獲取推流和拉流的完整地址,下面將指導(dǎo)大家開啟和觀看直播。開始直播1、打開OBS推流軟件(安裝過程一直next即可,本文不再贅述),來源點(diǎn)擊+號(hào),即可使用OBS捕獲任...
摘要:通過集成,可以從零開始,快速搭建出實(shí)時(shí)音視頻通信平臺(tái),可以應(yīng)用于語音和視頻社交在線教育和培訓(xùn)遠(yuǎn)程醫(yī)療在線會(huì)議直播等多種業(yè)務(wù)場景。集成之前,需要在官網(wǎng)控制臺(tái)創(chuàng)建應(yīng)用。使用服務(wù)之前,首先需要注冊(cè)賬號(hào)并且完成實(shí)名認(rèn)證。確定后,自動(dòng)生成。通過集成URTC SDK,可以從零開始,快速搭建出實(shí)時(shí)音視頻通信平臺(tái),可以應(yīng)用于語音和視頻社交、在線教育和培訓(xùn)、遠(yuǎn)程醫(yī)療、在線會(huì)議、直播等多種業(yè)務(wù)場景。 集成URT...
閱讀 3276·2021-11-22 14:44
閱讀 1122·2021-11-16 11:53
閱讀 1272·2021-11-12 10:36
閱讀 709·2021-10-14 09:43
閱讀 3702·2019-08-30 15:55
閱讀 3406·2019-08-30 14:14
閱讀 1746·2019-08-26 18:37
閱讀 3419·2019-08-26 12:12