知識點概要
- 字節(jié)流與字符流的概念
- 利用字節(jié)流對象完成文件讀取和寫入
一、Java IO簡介
IO可以理解為“I/O”,可理解為In和Out瞧甩,即輸入與輸出。所以弥鹦,IO體系的基本功能就是讀和寫亲配。
IO流:
- 作用:讀寫設(shè)備上的數(shù)據(jù),硬盤文件、內(nèi)存吼虎、網(wǎng)絡(luò)犬钢、鍵盤等。
- 根據(jù)數(shù)據(jù)的走向:輸入流和輸出流
- 根據(jù)處理的數(shù)據(jù)類型:字節(jié)流和字符流
字節(jié)流:可以處理所有類型的數(shù)據(jù)思灰,如MP3玷犹、圖片、文字洒疚、視頻等歹颓。 在讀取時,讀到一個字節(jié)就返回一個字節(jié)油湖。
==在Java中巍扛,對應(yīng)的類都是以stream結(jié)尾。==
字符流:僅能夠處理純文本數(shù)據(jù)乏德,如txt文本等撤奸。在讀取時,讀到一個或多個字節(jié)喊括,先查找指定的編碼表胧瓜,然后將查到的字符返回。
二郑什、字符府喳、字節(jié)與編碼
字節(jié)(Byte):通過網(wǎng)絡(luò)傳輸信息或內(nèi)存中存儲信息的單位,是計算機信息技術(shù)用于計量存儲和傳輸容量的一種計量單位蘑拯。
一字節(jié)等于8位二進制钝满,即一個8位的二進制數(shù),是一個很具體的存儲空間申窘。如0x01,0x45,0xFA...
字符(Char):字符是人們使用的記號舱沧,是抽象意義上的一個符號。
字符集(Charset):字符集也叫做編碼偶洋。編碼標(biāo)準(zhǔn)中規(guī)定所包含字符的集合就是字符集熟吏。規(guī)定每個字符分別用一個字節(jié)還是多個字節(jié)存儲,用那些字節(jié)存儲玄窝,這個規(guī)定就叫做“編碼”牵寺。
ANSI:字符串在內(nèi)存中,如果“字符”是以ANSI編碼形式存在的恩脂,一個字符可能用一個字節(jié)或者多個字節(jié)來展示帽氓,那么我們稱這種字符串為“ANSI”字符串或多字節(jié)字符串。不同ANSI編碼所規(guī)定的標(biāo)準(zhǔn)是不同的俩块,因此黎休,對于一個給定的多字節(jié)字符串浓领,我們必須知道它采用的是哪一種編碼規(guī)則,才能夠知道它包含了哪些“字符”势腮。
Unicode:字符串在內(nèi)存中联贩,如果字符是以Unicode中的序號存在的,那么我們稱折中字符串為Unicode字符串或者寬字節(jié)字符串捎拯。對于Unicode字符串來說泪幌,不管在什么環(huán)境下,它所代表的內(nèi)容總是不變的署照。用來給Unicode字符集編碼的標(biāo)準(zhǔn)有很多種祸泪,比如UTF-8等。
三建芙、使用字節(jié)流讀取數(shù)據(jù)
準(zhǔn)備文本文件hello.txt没隘,存放的路徑為src/files/readTestFile.txt
,里面的內(nèi)容如下:
hello world
小飛俠
案例1:文件讀取
public class ReadByteStream {
public static void main(String[] args) {
try {
// 創(chuàng)建文件讀入字節(jié)流對象禁荸,用文件的路徑參數(shù)進行初始化
FileInputStream fs = new FileInputStream("src/files/readTestFile.txt");
// 字節(jié)數(shù)組作為讀入數(shù)據(jù)的緩沖區(qū)
byte input[] = new byte[100];
// 將數(shù)據(jù)讀取到input數(shù)組中
String str;
while (fs.read(input) != -1) {
str = new String(input, "UTF-8");
// str = new String(input, "GBK");
System.out.println(str);
}
// 關(guān)閉文件讀入字節(jié)流對象
fs.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
測試1:
使用str = new String(input, "UTF-8");
讀取輸出如下:
hello world
小飛俠
中文顯示正常右蒲。
測試2:
使用str = new String(input, "GBK");
讀取輸出如下:
hello world
灝忛渚?
中文顯示出現(xiàn)了亂碼。這是因為寫入的時候采用了UTF-8進行編碼屡限,讀取的時候卻強制使用了GBK進行解碼,自然導(dǎo)致讀取出來的內(nèi)容發(fā)生錯亂炕倘。
代碼實例2:文件寫入
public class WriteByteStream {
public static void main(String[] args) {
try {
// 待寫入的內(nèi)容
String outString = "write by 小飛俠";
// 創(chuàng)建文件輸出流對象
FileOutputStream fos = new FileOutputStream("src/files/writeTestFile.txt");
// 輸出緩沖區(qū)
byte output[] = outString.getBytes("UTF-8");
// 從緩沖區(qū)寫入到流對象钧大,并刷新流寫入到文件
fos.write(output);
fos.flush();
// 關(guān)閉輸出流對象
fos.close();
System.out.println("done");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
測試1:
writeTestFile.txt
中內(nèi)容如下,且多次寫入會發(fā)生內(nèi)容覆蓋
write by 小飛俠
代碼實例3:文件拷貝
package com.netease.fileIO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 功能描述:利用字節(jié)流對象實現(xiàn)文件拷貝
*
* @author louxj424
*
*/
public class CopyByteStream {
public static void main(String[] args) {
try {
// 創(chuàng)建文件的讀入和寫入字節(jié)流對象罩旋,并用文件位置進行初始化
FileInputStream fis = new FileInputStream("src/pictures/pic1.jpg");
FileOutputStream fos = new FileOutputStream("src/pictures/pic1_new.jpg");
// 緩沖區(qū)的字節(jié)數(shù)組
byte input[] = new byte[100];
// read正常的返回值為成功寫入到byte數(shù)組的字節(jié)數(shù)啊央,如果返回-1則說明寫完了。
while (fis.read(input) != -1) {
fos.write(input);
}
// 關(guān)閉文件讀入和寫入流
fos.close();
fis.close();
System.out.println("done");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
測試結(jié)果:
刷新工程目錄后涨醋,pictures文件夾下出現(xiàn)了新文件pic1_new.jpg
文件瓜饥。
四、使用帶有緩沖區(qū)的字節(jié)流讀取數(shù)據(jù)
package com.netease.fileIO;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 使用BufferedInputStream浴骂,通過緩存讀取大文件乓土。
* 在代碼編寫的過程中,通過不斷地調(diào)整緩沖區(qū)以及數(shù)組的大小溯警,找到一個合適的數(shù)值趣苏,前者影響磁盤讀寫次數(shù),后者影響處理時間梯轻。
*
* @author louxj424
*
*/
public class ReadByBuffertoStream {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
// 帶有緩沖的輸入輸出流的讀寫效率是非常高的食磕。
FileInputStream fis = new FileInputStream("src/JavaCode.pdf");
BufferedInputStream bis = new BufferedInputStream(fis, 10000);
FileOutputStream fos = new FileOutputStream("src/NewJavaCode.PDF");
BufferedOutputStream bos = new BufferedOutputStream(fos, 10000);
// 大型文件對應(yīng)的數(shù)組應(yīng)該大一些,小文件的數(shù)組應(yīng)當(dāng)小一些喳挑,在實踐中不斷嘗試和優(yōu)化彬伦。
byte input[] = new byte[10000];
int count = 0;
long startTime = System.currentTimeMillis();
while (bis.read(input) != -1) {
bos.write(input);
count++;
// System.out.println("文件讀取完畢滔悉!");
}
bos.close();
fos.close();
bis.close();
fis.close();
long endTime = System.currentTimeMillis();
System.out.println("讀取了" + count + "次");
System.out.println("耗時" + (float) (endTime - startTime) / (1000) + "秒");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
五、使用字符流寫數(shù)據(jù)
代碼實例:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
/**
* 利用字符流讀寫文件實現(xiàn)文本文件的拷貝功能
*
* @author louxj424
*
*/
public class CopyByCharStream {
public static void main(String[] args) {
try {
// 將創(chuàng)建的文件對象傳入文件輸入流单绑,該流為字節(jié)流
FileInputStream fis = new FileInputStream("src/files/readTestFile.txt");
FileOutputStream fos = new FileOutputStream("src/files/writeTestFile.txt");
// 將字節(jié)流轉(zhuǎn)換為字符流回官,指定字符集
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
// 創(chuàng)建一個字符數(shù)組
char input[] = new char[100];
int len = 0;
// read函數(shù)的正常返回值為實際讀取的字符數(shù)組的長度,-1代表已經(jīng)讀取到了文件末尾
while ((len = isr.read(input)) != -1) {
/*
* 第一個參數(shù)代表偏移量询张,參數(shù)值0表示從字符數(shù)組的開始位置讀取; 第二個參數(shù)為讀取的長度孙乖,值l為read()函數(shù)的返回值.
*/
String inputString = new String(input, 0, len);
// System.out.println(inputString);
osw.write(inputString);
}
// 關(guān)閉流,后打開的先關(guān)閉份氧,先打開的后關(guān)閉
isr.close();
osw.close();
fos.close();
fis.close();
System.out.println("Done");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
六唯袄、使用帶有緩沖的字符流讀寫數(shù)據(jù)
代碼實踐:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
/**
* 演示:使用帶有緩沖的字符流讀寫數(shù)據(jù)
*
* @author louxj424
*
*/
public class ReadWriteByBufferedStream {
public static void main(String[] args) {
try {
// 將創(chuàng)建的文件對象傳入文件輸入流,該流為字節(jié)流
FileInputStream fis = new FileInputStream("src/files/readTestFile.txt");
FileOutputStream fos = new FileOutputStream("src/files/writeTestFile.txt");
// 將字節(jié)流轉(zhuǎn)換為字符流蜗帜,指定字符集
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
BufferedReader br = new BufferedReader(isr);
// 自帶緩沖區(qū)恋拷,當(dāng)緩沖區(qū)被寫滿之后才會向硬盤真正寫入數(shù)據(jù),寫入效率增加
// BufferedWriter bw=new BufferedWriter(osw);
/*
* out A character-output stream autoFlu * sh A boolean; if true,
* the println, printf, or format methods will flush the output
* buffer
*/
PrintWriter pw = new PrintWriter(osw, true);
// 讀取文件的一行數(shù)據(jù)厅缺,返回null說明讀取到了文件末尾
String input;
while ((input = br.readLine()) != null) {
// bw.write(input);
pw.println(input);
}
// 將緩沖區(qū)內(nèi)容強制輸出蔬顾,以免造成緩沖區(qū)未寫滿程序關(guān)系造成數(shù)據(jù)丟失
pw.flush();
br.close();
// bw.close();
pw.close();
// 關(guān)閉流,后打開的先關(guān)閉湘捎,先打開的后關(guān)閉
isr.close();
osw.close();
fos.close();
fis.close();
System.out.println("Done");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
七诀豁、FileReader與FileWriter
代碼示例:
package com.netease.fileIO;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import jdk.jfr.events.FileWriteEvent;
public class TestFileReadWriter {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
// 讀取文件的文本數(shù)據(jù)
FileReader fr = new FileReader("src/new Hello.txt");
BufferedReader br = new BufferedReader(fr);
FileWriter fw = new FileWriter("src/new Hello2.txt");
BufferedWriter bw = new BufferedWriter(fw);
String line;
while ((line = br.readLine()) != null) {
bw.write(line + "\n");
}
bw.flush();
bw.close();
fw.close();
br.close();
fr.close();
System.out.println("Done");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
八、讀取配置文件參數(shù)信息
package com.netease.java.learn.IO.file;
import java.io.InputStream;
import java.util.Properties;
/**
* 配置文件鍵值對信息讀取示例
*
* @author louxj424
*
*/
public class PropertiesLoader {
private static final String DB_DRIVER = "DB_DRIVER";
private static final String DB_URL = "DB_URL";
private static final String DB_USER = "DB_USER";
private static final String DB_PASSWORD = "DB_PASSWORD";
// 這里路徑寫法適用于配置文件與源碼文件不在一個文件目錄的情形窥妇,使用的是絕對目錄的表示方法舷胜,
// 這里的"/"表示的src的根目錄
private static final String PROPERTIES_FILE = "/files/jdbc.properties";
private static String driver;
private static String url;
private static String username;
private static String password;
public static void main(String[] args) {
// 用來保存屬性文件中中的鍵值對
Properties properties = new Properties();
try {
// 讀取屬性文件中的內(nèi)容,將其讀取到一個輸入流中
// 使用詳解介紹可以參考文章:https://www.cnblogs.com/macwhirr/p/8116583.html
InputStream is = PropertiesLoader.class.getResourceAsStream(PROPERTIES_FILE);
// 從輸入流中讀取屬性列表:屬性文件中的鍵值對列表
properties.load(is);
} catch (Exception e) {
e.printStackTrace();
System.out.println("=================配置文件讀取錯誤=================");
}
// 將讀取到的值賦值給類的成員變量
driver = properties.getProperty(DB_DRIVER);
url = properties.getProperty(DB_URL);
username = properties.getProperty(DB_USER);
password = properties.getProperty(DB_PASSWORD);
System.out.println(DB_DRIVER + ":" + driver);
System.out.println(DB_URL + ":" + url);
System.out.println(DB_USER + ":" + username);
System.out.println(DB_PASSWORD + ":" + password);
}
}
src/files/jdbc.properties目錄下的配置文件內(nèi)容信息如下:
DB_DRIVER=com.mysql.jdbc.Driver
DB_URL=jdbc:mysql://localhost/jsp_db
DB_USER=root
DB_PASSWORD=123456