轉換流(OutputStreamWriter/InputStreamReader) 檔案拷貝 字元編碼(亂碼)
阿新 • • 發佈:2018-12-05
一:轉換流</fon
在這篇部落格中介紹了位元組流和字元流:
https://blog.csdn.net/sophia__yu/article/details/84678506
其實可以將位元組流轉換為字元流,也就是轉換流。
轉換流用於將底層的位元組流轉為字元流供子類使用。
位元組輸出流–>字元輸出流:OutputStreamWriter。
public OutputStreamWriter(OutputStream out)
位元組輸入流—>字元輸入流: InputStreamReader
public InputStreamReader(InputStream in) </font><br />
流的繼承關係:
public class FileWriter extends OutputStreamWriter;
public class OutputStreamWriter extends Writer;
public class FileReader extends InputStreamReader;
public class InputStreamReader extends Reader
將位元組流轉換為字元流例項:
package CODE.IO;
import java.io.*;
//將位元組流轉換為字元流
public class Zhunhuan {
//取得終端物件:這裡的終端是檔案
public static void main(String[] args) throws Exception{
File file=new File("C:"+File.separator+"Users"+
File.separator+ "lenovo"+File.separator+"Desktop"+
File.separator+"Test.txt");
//取得終端輸出流
OutputStream out=new FileOutputStream (file);
OutputStreamWriter wr=new OutputStreamWriter(out); //將位元組輸出流轉換為字元輸出流
wr.write("hello pick"); //字元輸入流的字串寫入
wr.close(); //關閉流
}
}
檔案拷貝
資料的拷貝是通過流的方式來完成,而流分為位元組流和字元流。一般位元組流用於拷貝圖片音樂等,字元流可以用於中文的拷貝。
拷貝資料可以採用邊讀邊寫(讀一個位元組拷一個位元組);也可以採用利用緩衝區(開闢一個數據),一次性讀很多資料放在緩衝區,然後進行寫入。
1.讀一個位元組拷一個位元組:
package CODE.JavaIo;
import java.io.*;
//拷貝圖片
public class Copy {
public static void main(String[] args) throws Exception{
String sourceFilePath="C:"+File.separator+"Users"+File.separator+
"lenovo"+File.separator+"Desktop"+
File.separator+"pick.jpg";
String destFilePath="C:"+File.separator+"Users"+File.separator+
"lenovo"+File.separator+"Desktop"+
File.separator+"sophia.jpg";
copyFile(sourceFilePath,destFilePath);
}
public static boolean copyFile(String sourceFilePath,String destFilPath) throws Exception
{
//1.取得終端物件,終端是檔案
File sourceFile=new File(sourceFilePath);
File destFile=new File(destFilPath);
if(!sourceFile.getParentFile().exists())
{
System.out.println("原始檔父目錄不存在");
sourceFile.getParentFile().mkdirs();
return false;
}
if(!sourceFile.exists())
{
System.out.println("拷貝原始檔不存在");
return false;
}
if(!destFile.getParentFile().exists())
{
System.out.println("目標檔案父目錄不存在");
destFile.getParentFile().mkdirs();
return false;
}
//現在具備拷貝條件
//2.取得檔案的輸入輸出流
InputStream in=new FileInputStream(sourceFile); //從原始檔讀取資料
OutputStream out=new FileOutputStream(destFile); //目標檔案是寫入資料
//3.讀取或寫入資料
long start=System.currentTimeMillis();
int len=0;
while((len=in.read())!=-1) //in.read()是一次讀取一個位元組,返回的是讀取的一個位元組資料,當返回-1讀取完畢
{
out.write(len); //將讀取到1位元組資料寫入目標檔案
}
long end=System.currentTimeMillis();
System.out.println("拷貝耗時:"+(end-start)+"毫秒"); //1642毫秒
//關閉流
in.close();
out.close();
return true;
}
}
2.利用緩衝區:
public class Copy {
public static void main(String[] args) throws Exception{
String sourceFilePath="C:"+File.separator+"Users"+File.separator+
"lenovo"+File.separator+"Desktop"+
File.separator+"pick.jpg";
String destFilePath="C:"+File.separator+"Users"+File.separator+
"lenovo"+File.separator+"Desktop"+
File.separator+"sophia.jpg";
copyFile(sourceFilePath,destFilePath);
}
public static boolean copyFile(String sourceFilePath,String destFilPath) throws Exception
{
//1.取得終端物件,終端是檔案
File sourceFile=new File(sourceFilePath);
File destFile=new File(destFilPath);
if(!sourceFile.getParentFile().exists())
{
System.out.println("原始檔父目錄不存在");
sourceFile.getParentFile().mkdirs();
return false;
}
if(!sourceFile.exists())
{
System.out.println("拷貝原始檔不存在");
return false;
}
if(!destFile.getParentFile().exists())
{
System.out.println("目標檔案父目錄不存在");
destFile.getParentFile().mkdirs();
return false;
}
//現在具備拷貝條件
//2.取得檔案的輸入輸出流
InputStream in=new FileInputStream(sourceFile); //從原始檔讀取資料
OutputStream out=new FileOutputStream(destFile); //目標檔案是寫入資料
//3.讀取或寫入資料
long start=System.currentTimeMillis();
int len=0;
byte[] data=new byte[1024]; //緩衝區為1024位元組
while((len=in.read(data))!=-1) //in.read(data)將讀取的資料放入data陣列,返回的是實際讀取位元組數,當返回-1,讀取完畢
{
out.write(data); //將data陣列內容寫入
}
long end=System.currentTimeMillis();
System.out.println("拷貝耗時:"+(end-start)+"毫秒"); //16毫秒
//關閉流
in.close();
out.close();
return true;
}
}
字元編碼
常用字元編碼
1. GDK DB2312:國際編碼。
GBK既包含簡體中文也包含繁體中文。
DB2312只包含簡體中文。
2. UNICODE :java提供的16進位制編碼,可以描述世界上任意的文字。由於採用16進位制編碼,導致編碼的體積太大,造成網路傳輸負擔。
3. ISO8859-1 :瀏覽器預設編碼,國際通用編碼,不支援中文。
4. UTF 編碼:(UTF-8:8進位制UTF編碼):相當於結合了ISO-8859-1和UNICODE編碼,支援所有語言而且體積小。
所以在實際開發中,採用UTF-8編碼。
亂碼產生原因
產生亂碼的95%原因一般是編解碼不一致。
System.getProperties().list(System.out); //當前作業系統的預設編碼格式:UTF-8
如果系統所用的編碼與程式所用編碼不同,那麼強制轉換就會出現亂碼。
package CODE.JavaIo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
//亂碼
public class Unicode {
public static void main(String[] args) throws Exception{
//System.getProperties().list(System.out); //當前作業系統的預設編碼格式:UTF-8
File file=new File("C:"+File.separator+"Users"+
File.separator+ "lenovo"+File.separator+"Desktop"+
File.separator+"Test.txt");
OutputStream out=new FileOutputStream(file);
String str="哈嘍 pick";
out.write(str.getBytes("ISO8859-1"));
//以ISO--8859-1格式寫入,但是作業系統預設解碼是UTF-8,會出現亂碼
out.close();
}
}
ISO8859-1不支援中文,所以對"哈嘍"解碼時出現亂碼。