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();
}
}
}
相關文章
- IDEA Activiti Designer外掛---actiBPM漢字亂碼問題Idea
- 解決中文亂碼問題
- 解決java socket在傳輸漢字時出現截斷導致亂碼的問題Java
- 行業乾貨-如何逆向解決QT程式漢化亂碼問題行業QT
- springmvc 解決中文亂碼問題SpringMVC
- MySql中文亂碼問題解決MySql
- Jmeter 解決中文亂碼問題JMeter
- 漢字編碼問題
- 解決Kali Linux 2020.1亂碼問題Linux
- TongWeb下亂碼問題解決思路Web
- java中亂碼問題解決方法Java
- js解決url中文亂碼問題JS
- cat 輸出亂碼問題解決
- 解決plsql中中文亂碼問題SQL
- flashfxp 亂碼,2種辦法解決flashfxp 亂碼問題
- phantomjs截圖中文亂碼問題解決JS
- JavaWeb 亂碼問題終極解決方案!JavaWeb
- 自定義RedisTemplate,解決Redis亂碼問題Redis
- Filter解決亂碼問題 -2024/11/6Filter
- 【日誌亂碼】解決Tomcat啟動控制檯亂碼問題Tomcat
- 解決Intellij IDEA中執行緩慢的問題,tomcat控制檯列印亂碼問題,國際化亂碼配置檔案亂碼解決IntelliJIdeaTomcat
- 雲伺服器中文亂碼問題解決伺服器
- 解決Url帶中文引數亂碼問題
- Sublime Text 3 中文亂碼問題的解決
- python json.dumps中文亂碼問題解決PythonJSON
- SqlServer資料庫中文亂碼問題解決SQLServer資料庫
- 完美解決jspdf各種中文亂碼問題JS
- JMeter響應亂碼問題解決方案教程JMeter
- 【IDL】IDL中亂碼問題的解決方法
- 解決zabbix圖形化中文亂碼問題
- LiveCharts中文顯示亂碼問題的解決Echarts
- mysql使用source 命令亂碼問題解決方法MySql
- 解決Charles手機抓包出現unknown和亂碼的問題
- 透過Treeset解決隨機數排序問題隨機排序
- 手把手教你寫網路爬蟲(8):徹底解決亂碼問題爬蟲
- 解決Eclipse中文註釋部分亂碼的問題Eclipse
- 解決excel開啟.csv檔案亂碼問題Excel
- URL地址中的中文亂碼問題的解決
- Mysql中文亂碼問題的最佳解決方法MySql