字節(jié)流
- InputStream 輸入字節(jié)流
- OutputStream 輸出字節(jié)流
輸入字節(jié)流----InputStream
InputStream 是所有的輸入字節(jié)流的父類默穴,它是一個(gè)抽象類禁悠。同樣的來(lái)看它的子類。
FileInputStream 繼承自InputStream
構(gòu)造方法:
//傳一個(gè)文件路徑(字符串)
public FileInputStream(String var1) throws FileNotFoundException {
this(var1 != null?new File(var1):null);
}//如:FileInputStream in=new FileInputStream(String path);
//傳一個(gè)文件
public FileInputStream(File var1) throws FileNotFoundException {
....
}//如:FileInputStream in=new FileInputStream(new File(String path));
//不常用
public FileInputStream(FileDescriptor var1) {
...
}
主要方法
int read();//返回值int,若返回值為-1脯爪,則代表已經(jīng)讀完珊佣,是不是和字符流很像,但每次讀一個(gè)字節(jié)披粟,并打印,如果存在中文咒锻,可能會(huì)亂碼
int read(byte[] bytes);//每次讀bytes字節(jié)
代碼演示:
/**
* 需求:控制臺(tái)輸出本文件內(nèi)容
*/
public class Demo {
//文件地址
public static final String PATH = "/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/com/example/Demo1.java";
//文件名
public static final String NAME = "copyTest1.java";
public static void main(String[] args) {
// read();//測(cè)試InputStream 的read()方法
reads();
}
/**
* 測(cè)試read(byte[] bytes)
* 可以控制字符集
*/
private static void reads() {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(PATH);
byte[] bytes = new byte[inputStream.available()];//inputStream.available()獲取文件長(zhǎng)度
//讀取的字節(jié)長(zhǎng)度
int len = inputStream.read(bytes);//將數(shù)據(jù)一次性讀取到字節(jié)數(shù)組中
System.out.println("讀取長(zhǎng)度" + len + "\n" + new String(bytes, "utf-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 測(cè)試read()
* 每次讀一個(gè)字節(jié),并打印,如果存在中文守屉,可能會(huì)亂碼
*/
private static void read() {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(PATH);
int len = 0;
while ((len = inputStream.read()) != -1) {
System.out.print((char) len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
結(jié)果----read()惑艇,出現(xiàn)了亂碼.
結(jié)果----read(byte[]bytes),設(shè)置了字符集拇泛,沒(méi)出現(xiàn)亂碼.
有沒(méi)有覺(jué)得都差不多.
輸出字節(jié)流----OutputStream
OutputStream 是所有的輸入字節(jié)流的父類滨巴,它是一個(gè)抽象類。同樣的來(lái)看它的子類俺叭。
FileOutStream 繼承自O(shè)utputStream
構(gòu)造方法:
//是不是和FileWriter很像恭取,第一個(gè)參數(shù)目的是創(chuàng)建一個(gè)向指定 File 對(duì)象表示的文件中寫(xiě)入數(shù)據(jù)的文件輸出流。如果第二個(gè)參數(shù)為 true熄守,則將字節(jié)寫(xiě)入文件末尾處蜈垮,而不是寫(xiě)入文件開(kāi)始處。
public FileOutputStream(String var1) throws FileNotFoundException {
....
}
public FileOutputStream(String var1, boolean var2) throws FileNotFoundException {
.....
}
public FileOutputStream(File var1) throws FileNotFoundException {
this(var1, false);
}
public FileOutputStream(File var1, boolean var2) throws FileNotFoundException {
......
}
public FileOutputStream(FileDescriptor var1) {
.....
}
主要方法
- void write(byte[]bytes);//寫(xiě)字節(jié)數(shù)組
寫(xiě)純文本文件-----案例
-
Config類代碼:(通用案例1裕照,2攒发,3)
public class Config { public static final String PATH="/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/files"; }
-
主要代碼
private static final String fileName = "testOutput.java"; /** * */ private static void write() { FileOutputStream outputStream = null; try { outputStream = new FileOutputStream(Config.PATH + fileName); outputStream.write("你好啊,美女".getBytes()); } catch (Exception e) { e.printStackTrace(); }finally { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
結(jié)果
拷貝純文本文件-----案例(讀晋南,寫(xiě))
-
代碼
/** * 拷貝本類文件 */ private static void copyFile() { String copyName = "copy.java"; String sourcePath = "/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/com/example/Demo2.java"; FileInputStream inputStream = null; FileOutputStream outputStream = null; try { inputStream = new FileInputStream(sourcePath); outputStream = new FileOutputStream(Config.PATH + copyName); byte[] bytes = new byte[inputStream.available()]; inputStream.read(bytes); outputStream.write(bytes); } catch (Exception e) { e.printStackTrace(); } finally { try { inputStream.close(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
-
結(jié)果
拷貝圖片-----案例(讀惠猿,寫(xiě))
-
代碼
/** * 拷貝圖片step1.png */ private static void copyPicture() { String picSource = "/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/images/step1.png"; String copyName = "copyPic.png"; FileInputStream inputStream = null; FileOutputStream outputStream = null; try { inputStream = new FileInputStream(picSource); outputStream = new FileOutputStream(Config.PATH + copyName); //定義緩沖區(qū)--字節(jié)數(shù)組 byte[] bytes=new byte[1024]; //每次最多讀取1K節(jié)字 int len=-1; //每次讀取的字節(jié)長(zhǎng)度 while((len=inputStream.read(bytes))!=-1){ //-1代表的是文件結(jié)尾標(biāo)識(shí) outputStream.write(bytes, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { try { inputStream.close(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
-
結(jié)果
同樣的,字節(jié)流也有帶緩沖的负间,基本都是一樣的偶妖,當(dāng)讀寫(xiě)純文本的時(shí)候優(yōu)先考慮字符流,讀寫(xiě)非純文本的時(shí)候用字節(jié)流政溃。下面我們繼續(xù)看帶緩沖的字節(jié)流趾访,基本一樣。
帶緩沖的字節(jié)流讀寫(xiě)案例(BufferedInputStream 讀玩祟,BufferedOutputStream 寫(xiě))沒(méi)有關(guān)閉的流你們自行關(guān)閉腹缩。
-
Config 類
public class Config { public static final String PATH="/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/files"; }
-
測(cè)試類
/** * 帶緩沖的字節(jié)流 * <p> * 需求:使用帶緩沖的字節(jié)流拷貝文件 */ public class Demo3 { //純文本源文件路徑 private static final String txtPath = "/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/com/example/Demo2.java"; //拷貝后的純文本文件名 private static final String txtName = "copy.java"; //圖片源文件路徑 private static String picPath = "/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/images/step1.png"; //拷貝后的圖片名 private static String picName = "copyPic.png"; public static void main(String[] args) { //copy(txtPath, txtName); copy(picPath, picName); } /** * 拷貝文件 * Config.PATH 是上面提到的 * * @param sourcePath 源路徑 * @param targetName 文件名 */ private static void copy(String sourcePath, String targetName) { //申明變量 FileInputStream inputStream = null; BufferedInputStream bufferedInputStream = null; FileOutputStream outputStream = null; BufferedOutputStream bufferedOutputStream = null; //實(shí)例化變量 try { inputStream = new FileInputStream(sourcePath); bufferedInputStream = new BufferedInputStream(inputStream); outputStream = new FileOutputStream(Config.PATH + targetName); bufferedOutputStream = new BufferedOutputStream(outputStream); byte[] bytes = new byte[2048];//大小可以自己指定屿聋,但不要非常非常大空扎。 int len = 0; while ((len = bufferedInputStream.read(bytes)) != -1) { bufferedOutputStream.write(bytes, 0, len);//向緩沖區(qū)中寫(xiě)入指定長(zhǎng)度的數(shù)據(jù) bufferedOutputStream.flush();//將數(shù)據(jù)從內(nèi)存中寫(xiě)入到文件中 } } catch (Exception e) { e.printStackTrace(); } finally { try { bufferedInputStream.close();//關(guān)閉流(處理流),其中的包裝流會(huì)自動(dòng)關(guān)閉 bufferedOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
結(jié)果
都是一樣的润讥。
InputStram 綁定System.in 案例
public class Demo4 {
/**
* 打印從鍵盤(pán)輸入的字母转锈,直到輸入exit結(jié)束程序
* @param args
*/
public static void main(String[] args) {
InputStream inputStream = System.in;
int num = -1;
StringBuilder sb = new StringBuilder();
while (true) {
try {
num = inputStream.read();
//判斷字符是否換行
if (num == '\n') {
String line = sb.toString().trim();//去除兩邊的空格
if (line.equalsIgnoreCase("over")) {
break;
}
System.out.println(line); //打印輸入的一行數(shù)據(jù)(字母是大寫(xiě))
//重置字符串變量的內(nèi)容
sb.delete(0, sb.length());
}
sb.append((char) num);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
結(jié)果
可是兄弟們,你們看到打印字符串亂碼了嗎楚殿,字節(jié)流不能操作Unicode字符撮慨,由于Java采用16位的Unicode字符,
所以要使用基于字符的輸入輸出操作。所以有了字符流砌溺,以提供直接的字符輸入輸出的支持影涉。而字節(jié)流怎么轉(zhuǎn)成字符流呢,Java為我們提供了兩個(gè)類规伐,InputStreamReader蟹倾,
OutputStreamWriter。作為字節(jié)流和字符流的橋接猖闪,并可以設(shè)置字符編碼.
-
InputStreamReader 構(gòu)造方法
//來(lái)自源碼 // 接收一個(gè)字節(jié)流實(shí)例 public InputStreamReader(InputStream var1) { super(var1); try { this.sd = StreamDecoder.forInputStreamReader(var1, this, (String)null); } catch (UnsupportedEncodingException var3) { throw new Error(var3); } } //接受一個(gè)字節(jié)流實(shí)例和一個(gè)String 類型的參數(shù)鲜棠,再深入看代碼可猜測(cè)var2和字符集(charset)有關(guān)系 public InputStreamReader(InputStream var1, String var2) throws UnsupportedEncodingException { super(var1); if(var2 == null) { throw new NullPointerException("charsetName"); } else { this.sd = StreamDecoder.forInputStreamReader(var1, this, var2); } } //同 public InputStreamReader(InputStream var1, Charset var2) { super(var1); if(var2 == null) { throw new NullPointerException("charset"); } else { this.sd = StreamDecoder.forInputStreamReader(var1, this, var2); } } //基本一樣 public InputStreamReader(InputStream var1, CharsetDecoder var2) { super(var1); if(var2 == null) { throw new NullPointerException("charset decoder"); } else { this.sd = StreamDecoder.forInputStreamReader(var1, this, var2); } }
-
OutputStreamWriter 構(gòu)造方法(實(shí)參var2作用同InputStreamReader)
public OutputStreamWriter(OutputStream var1, String var2) throws UnsupportedEncodingException { super(var1); if(var2 == null) { throw new NullPointerException("charsetName"); } else { this.se = StreamEncoder.forOutputStreamWriter(var1, this, var2); } } public OutputStreamWriter(OutputStream var1) { super(var1); try { this.se = StreamEncoder.forOutputStreamWriter(var1, this, (String)null); } catch (UnsupportedEncodingException var3) { throw new Error(var3); } } public OutputStreamWriter(OutputStream var1, Charset var2) { super(var1); if(var2 == null) { throw new NullPointerException("charset"); } else { this.se = StreamEncoder.forOutputStreamWriter(var1, this, var2); } } public OutputStreamWriter(OutputStream var1, CharsetEncoder var2) { super(var1); if(var2 == null) { throw new NullPointerException("charset encoder"); } else { this.se = StreamEncoder.forOutputStreamWriter(var1, this, var2); } }
案例優(yōu)化,接收打印中文字符
/**
* 字節(jié)流培慌,字符流轉(zhuǎn)換
*/
public class Demo5 {
public static void main(String[] args) {
//輸入流綁定鍵盤(pán)輸入
InputStream inputStream = System.in;
//字符輸入流聲明
InputStreamReader inputStreamReader = null;
try {
//實(shí)例化帶有編碼格式的字符流
inputStreamReader = new InputStreamReader(inputStream, "utf-8");
//包裝
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line = null;
while (true) {
//判斷讀取
line = new String(bufferedReader.readLine());
if (line.trim().equalsIgnoreCase("exit")) {
break;
}
//打印輸出
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
結(jié)果
持續(xù)深入
/**
* 需求:接收鍵盤(pán)輸入的內(nèi)容豁陆,并打印到文件里去
*/
public class Demo6 {
public static void main(String[] args) {
//1. 通過(guò)轉(zhuǎn)換流,獲取到讀取鍵盤(pán)的字符輸入流
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String fileName = "copy.txt";//文件名
//涉及到了System.in,System.out,System.setOut(...),PrintWriter
//設(shè)置控制輸出的數(shù)據(jù)位置--保存到文件中
try {
//File.separator分隔符
System.setOut(new PrintStream(Config.PATH + File.separator + fileName));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//2. 通過(guò)轉(zhuǎn)換流吵护,將控制臺(tái)的字節(jié)流轉(zhuǎn)換成緩沖的字符流
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
//3. 開(kāi)始讀取數(shù)據(jù)
String line = null;
while (true) {
try {
line = reader.readLine().trim();
if (line.equalsIgnoreCase("exit")) {
break;
}
writer.write(line);
writer.newLine();
writer.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}