Java.nio-隨機讀寫解決漢字亂碼問題
筆者最近在用多執行緒來計算中文文字的標點符號數目,遇到了以下問題:
- 在Windows下,文字中漢字通常採用Unicode編碼,這就導致需要隨機
(RandomAccessFile)
讀取文字時,產生亂碼現象。 - 多執行緒計算前(假設有2個執行緒),需要將文字內容儘量等分成2份,並輸出到新的檔案中,再進行計算。
總體思路:
- 規定一次讀取的位元組數,再在儲存和輸出時轉化成GBK編碼
- 由於
RandomAccessFile
可以隨機定位讀取起始點,當規定了一次讀取的位元組數,也就規定了讀取結束點。 - 按行讀取,每一行的位元組有對應的陣列儲存,轉化成GBK後,寫入輸出文字。
- 由於
- 引入
java.nio
,在讀取檔案和轉化編碼時方便很多,筆者認為java.io
也可以實現。- 關於NIO的詳細教程可以參考:NIO系列教程
- 本文引入
java.nio.ByteBuffer
,java.nio.channels.FileChannel
,前者無需解釋,後者為通道,相當於流。
具體程式碼實現如下:
package Yue.IO;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* 將文字內容儘量分成n份,使n個執行緒處理對應的文字
*/
public class SplitFile {
int fileNum; //分離的檔案數
File fileIn = new File("E:\\白夜行.txt");
int bufSize;
SplitFile(int threadsNum) {
fileNum = threadsNum;
bufSize = (int) (fileIn.length() / fileNum); //一次讀取的位元組數
}
FileChannel fileChaIn, fileChaOut;
ByteBuffer rBuffer, wBuffer;
/*設定緩衝區,讀檔案時,最後一行往往不完整,需要將存在斷點的那一行儲存,與下一次讀文字時的第一行合併*/
byte[] temp = new byte[0];
/**
* 按行具體讀出每一個執行緒所要處理的文字內容
*
* @param NO Thread-NO
*/
public void readByLine(int NO) {
String enter = "\n";
byte[] lineByte; //儲存每一行讀取內容
/*確認讀取範圍*/
try {
RandomAccessFile raf = new RandomAccessFile(fileIn, "r");
raf.seek(NO * bufSize); //根據分離文字程式定位
fileChaIn = raf.getChannel();
rBuffer = ByteBuffer.allocate(bufSize);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fileChaIn.read(rBuffer) != -1) {
/*生成輸出檔案Part-No.txt*/
try {
fileChaOut = new RandomAccessFile("E:\\Part-" + NO + ".txt", "rws").getChannel();
wBuffer = ByteBuffer.allocateDirect(bufSize);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
/*根據一次讀取,確定本次輸出的位元組長度*/
int rSize = rBuffer.position();
byte[] bs = new byte[rSize];
rBuffer.rewind();
rBuffer.get(bs);
rBuffer.clear();
int startNum = 0;
int LF = 10; //換行符
int CR = 13; //回車符
boolean hasLF = false; //是否有換行符
for (int i = 0; i < rSize; i++) {
if (bs[i] == LF) {
hasLF = true;
int tempNum = temp.length;
int lineNum = i - startNum;
lineByte = new byte[tempNum + lineNum]; //陣列大小已經去掉換行符
/*把上一次讀取儲存在緩衝區的內容和本次讀取的這一行的內容合併,儲存到lineByte[]中*/
System.arraycopy(temp, 0, lineByte, 0, tempNum);
temp = new byte[0];
System.arraycopy(bs, startNum, lineByte, tempNum, lineNum);
/*把該行內容轉換成String型別,寫入輸出檔案中*/
String line = new String(lineByte, 0, lineByte.length, "GBK");
writeByLine(line + enter);
/*過濾回車和換行*/
if (i == rSize - 1 && bs[i + 1] == CR) {
startNum = i + 2;
} else {
startNum = i + 1;
}
}
}
/*對每次讀取的最後一行做特殊處理,將未讀完整的當前行不輸出,儲存在緩衝區中,與下一次讀取時合併*/
if (hasLF) {
temp = new byte[bs.length - startNum];
System.arraycopy(bs, startNum, temp, 0, temp.length);
} else {
/*相容單次讀取不足一行的情況*/
byte[] toTemp = new byte[bs.length + temp.length];
System.arraycopy(temp, 0, toTemp, 0, temp.length);
System.arraycopy(bs, 0, toTemp, temp.length, bs.length);
temp = toTemp;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileChaIn.close();
fileChaOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 寫入輸出檔案
*
* @param line 已轉換成String型別的當前行文字內容
*/
public void writeByLine(String line) {
try {
fileChaOut.write(wBuffer.wrap(line.getBytes("GBK")), fileChaOut.size());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
相關文章
- 解決JSP讀寫MYSQL亂碼問題JSMySql
- PLSQL中漢字顯示亂碼問題SQL
- 讀mysql中文亂碼問題解決方法MySql
- Java 讀檔案寫檔案 韓文 中文 亂碼問題解決方案Java
- Oracle客戶端toad漢字亂碼解決方法Oracle客戶端
- CKfinder CKeditor 上傳圖片 漢字 亂碼 解決方法
- 解決java socket在傳輸漢字時出現截斷導致亂碼的問題Java
- 解決中文亂碼問題
- 解決SSH亂碼問題
- jive 漢字問題終極解決辦法
- MySql中文亂碼問題解決MySql
- Jmeter 解決中文亂碼問題JMeter
- Java 解決中文亂碼問題Java
- RDSSQLSERVER解決中文亂碼問題SQLServer
- 解決MySQL中文亂碼問題MySql
- MYSQL亂碼問題解決方法MySql
- IDEA Activiti Designer外掛---actiBPM漢字亂碼問題Idea
- 對HTML標準的思考-記解決H5隨機顯示簡繁體漢字問題HTMLH5隨機
- Linux下的JFreeChart和 漢子驗證碼 中文亂碼問題解決方案Linux
- java中亂碼問題解決方法Java
- cat 輸出亂碼問題解決
- 解決plsql中中文亂碼問題SQL
- TongWeb下亂碼問題解決思路Web
- 解決使用Git Bash亂碼問題Git
- plsql查詢亂碼問題解決SQL
- 解決 plsql 遇到亂碼的問題SQL
- 解決Mysql匯入亂碼問題MySql
- oracle字元亂碼問題的解決Oracle字元
- 解決Flex裡的亂碼問題Flex
- 徹底解決程式亂碼問題
- flashfxp 亂碼,2種辦法解決flashfxp 亂碼問題
- C#隨機產生漢字C#隨機
- JavaWeb 亂碼問題終極解決方案!JavaWeb
- java中解決request中文亂碼問題Java
- SpringMvc解決Restful中文亂碼問題SpringMVCREST
- 解決confluence的亂碼問題
- 解決CentOS 中顯示亂碼問題CentOS
- python 中文亂碼問題解決方案Python