字節流和字符流讀取的文件的數據都是一堆我們人類看不懂的數字,熟悉ASCII表的可能還能看得懂英文字母(字符估計就夠嗆了),怎樣轉換一下讓我們能看的懂呢?方法有很多,下面將通過例子來逐一實現他們。
1、我們首先想到的恐怕非InputStreamReader
了,把字節流轉成字符流不就行了嗎。
@Test
public void inputStream2String(){
try (FileInputStream fis = new FileInputStream("test.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis))){
StringBuilder sb = new StringBuilder();
String line = null;
boolean firstLine = true;
while ((line = br.readLine())!=null){
if (!firstLine){
sb.append(System.getProperty("line.separator")); //如果不是第一行,添加系統換行符
} else {
firstLine = false;
}
sb.append(line);
}
System.out.println(sb.toString());
} catch (IOException e){
e.printStackTrace();
}
}
2、其實我們還有更簡單的方法,根本不用經過字節流,而且還省了對換行符的判斷。
@Test
public void inputStream2String(){
try (FileInputStream fis = new FileInputStream("test.txt")){
StringBuilder sb = new StringBuilder();
byte[] bytes = new byte[1024];
int len = 0;
while ((len=fis.read(bytes))!=-1){
sb.append(new String(bytes, 0, len));
}
System.out.println(sb.toString());
} catch (IOException e){
e.printStackTrace();
}
}
3、上面的方法有很多重複性代碼是固定的,可以提出來,所以就有了第三方庫幫我們做好了這一切,使用Apache的IO庫,代碼會更簡潔。
這裏使用的是Maven加載的依賴,目前最新jar包是2017年的,還沒有出新的。添加的依賴如下:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
Java代碼很簡單
@Test
public void inputStream2String(){
try (FileInputStream fis = new FileInputStream("test.txt")){
String string = IOUtils.toString(fis, StandardCharsets.UTF_8); //不指定編碼方式的toString在2.5被遺棄了
System.out.println(string);
} catch (IOException e){
e.printStackTrace();
}
}
IOUtils.toString的進一步封裝。
@Test
public void inputStream2String(){
File file = new File("test.txt");
try {
//這個方法的底層還是使用的IOUtils.toString實現的
//並且使用了try-with-resource,自動關閉流
String string = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
System.out.println(string);
} catch (IOException e) {
e.printStackTrace();
}
}
這個類庫還有兩種方式具體代碼就不寫了,只把方法貼上:
- IOUtils.readLines(final InputStream input, final Charset encoding)
- Files.readLines(final File file, final Charset encoding) 這個方法是上面方法的封裝
4、既然你Apache實現了這個工具,那我Guava豈能甘爲人後。
@Test
public void inputStream2String(){
try (FileInputStream fis = new FileInputStream("test.txt");
BufferedReader bf = new BufferedReader(new InputStreamReader(fis))){
//提示這是Beta版本,不穩定
//接收的參數爲Readable
String string = CharStreams.toString(bf);
System.out.println(string);
} catch (IOException e){
e.printStackTrace();
}
}
5、Guava還有一種方式,按行讀取。
@Test
public void inputStream2String(){
try (FileInputStream fis = new FileInputStream("test.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr)){
List<String> stringList = CharStreams.readLines(br);
System.out.println(stringList.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
6、使用Java7的java.nio.file.Files實現讀取,也很簡單。但是這個方法是一次性把文件所有內容全部讀進內存,容易造成stack overflow。
@Test
public void inputStream2String(){
try{
byte[] bytes = Files.readAllBytes(Paths.get("test.txt"));
String string = new String(bytes);
System.out.println(string);
} catch (IOException e) {
e.printStackTrace();
}
}
7、使用Jdk5的Scanner
,同時支持英文和中文。
@Test
public void inputStream2String(){
try (FileInputStream fis = new FileInputStream("test.txt")){
Scanner scanner = new Scanner(fis, StandardCharsets.UTF_8);
while (scanner.hasNext()){
System.out.println(scanner.next());
}
} catch (IOException e){
e.printStackTrace();
}
}
8、最後一種權當了解,沒啥實際用途,只適合文件中包含英文字母或者字符的。
@Test
public void inputStream2String(){
try (FileInputStream fis = new FileInputStream("test.txt")){
int read = fis.read();
while (read != -1){
System.out.println("read = " + (char)read);
read = fis.read();
}
} catch (IOException e){
e.printStackTrace();
}
}
總結
這麼多種方法,推薦使用apache或者gson的第三方庫。不過gson目前還是測試版本,悠着點。