archive 是 flutter 上的一個文件壓縮與解壓的類庫,支持 zip,tar,zlip,gzip,zip2,xz 格式的壓縮與解壓。
archive 的使用
archive 主要通過 Archive,ArchiveFile,ZipEncoder,ZipDecoder 三個類來實(shí)現(xiàn)文件的壓縮和解壓。
ArchiveFile 表示壓縮包內(nèi)的一個文件。
Archive 表示一個壓縮包。
ZipEncoder 表示 zip 編碼器。
ZipDecoder 表示 zip 解碼器。
文件壓縮:
final zipFile = File("text.zip");
final archive = Archive();
var str="中文";
final archiveFile=ArchiveFile.string("test.txt", str); //將壓縮內(nèi)容添加到ArchiveFile
archive.addFile(archiveFile); //將ArchiveFile添加到Archive
final zipData = ZipEncoder().encode(archive); //使用zip編碼
zipFile.writeAsBytesSync(zipData!); //寫入到壓縮文件
文件解壓:
final zipFile = File("text.zip");
var archive=ZipDecoder().decodeBytes(zipFile.readAsBytesSync()); //讀取文件內(nèi)容,使用ZipDecoder解碼
ArchiveFile? f=archive.findFile("test.txt"); //從壓縮包內(nèi)尋找文件
var content=f?.content; //獲取內(nèi)容
亂碼分析
對于非中文內(nèi)容來說,直接使用以上代碼來實(shí)現(xiàn)壓縮和解壓是不會導(dǎo)致亂碼,但是對于中文來說卻會導(dǎo)致亂碼。
首先來分析 ArchiveFile.string()
方法做了什么。
ArchiveFile.string(this.name, String content,
[this._compressionType = STORE]) {
size = content.length;
_content = Uint8List.fromList(content.codeUnits);
_rawContent = InputStream(_content);
}
能看到,該方法首先獲取傳入字符串的 utf-16 編碼的列表,再將其轉(zhuǎn)為 uint8 列表。uint8 在 flutter 中表示 8 位比特(bit)的無符號數(shù),范圍為 [0,256)
。因?yàn)槲募褪前醋止?jié)(Byte)存儲的,一個字節(jié)由 8 位比特組成,范圍跟 uint8 一致。
但是對于中文來說,大小是超過 256 的,所以當(dāng)使用 Uint8List.fromList()
將中文從 utf-16 強(qiáng)轉(zhuǎn)為 uint8,會導(dǎo)致其被截斷,從而導(dǎo)致亂碼。
從下面測試?yán)又幸材芸闯鰜恚?/p>
String str="中文";
var list=str.codeUnits;
print(list);
var list2=Uint8List.fromList(list);
print(list2);
//運(yùn)行結(jié)果為:
[20013, 25991]
[45, 135]
所以對于中文來說,并不能直接強(qiáng)制為 uint8,需要對其進(jìn)行編碼再進(jìn)行存儲,中文編碼方式存在 utf-8,gbk 等,而 flutter 支持 utf-8 編碼,但不支持 gbk 編碼。對于 utf-8 編碼來說,中文需要 3 個字節(jié)來存儲。
utf8.encode(); //編碼
utf8.decode(); //解碼
我們再來看,ArchiveFile
的構(gòu)造方法除了 ArchiveFile.string()
外,還有
ArchiveFile(this.name, this.size, dynamic content,
[this._compressionType = STORE]) {
name = name.replaceAll('\\', '/');
if (content is Uint8List) {
_content = content;
_rawContent = InputStream(_content);
if (size <= 0) {
size = content.length;
}
} else if (content is InputStream) {
_rawContent = InputStream.from(content);
if (size <= 0) {
size = content.length;
}
} else if (content is InputStreamBase) {
_rawContent = content;
if (size <= 0) {
size = content.length;
}
} else if (content is TypedData) {
_content = Uint8List.view(content.buffer);
_rawContent = InputStream(_content);
if (size <= 0) {
size = (_content as Uint8List).length;
}
} else if (content is String) {
_content = content.codeUnits;
_rawContent = InputStream(_content);
if (size <= 0) {
size = content.codeUnits.length + 1;
}
} else if (content is List<int>) {
// Legacy
// This expects the list to be a list of bytes, with values [0, 255].
_content = content;
_rawContent = InputStream(_content);
if (size <= 0) {
size = content.length;
}
} else if (content is FileContent) {
_content = content;
}
}
當(dāng)傳入的 content
類型為 List<int>
時,直接賦值為 _content
,沒有進(jìn)行額外的操作。另外該方法還有另外一個參數(shù) _compressionType
,該參數(shù)需要傳入 ArchiveFile.STORE
,否則在進(jìn)行解壓時,archiveFile.content
會報錯:Unhandled Exception: RangeError: Value not in range: -6128
文章來源:http://www.zghlxwxcb.cn/news/detail-598479.html
解決辦法
所以最后處理中文亂碼的解決辦法就是先對其進(jìn)行 utf-8 編碼,再壓縮。解壓后,對其進(jìn)行 utf-8 解碼,獲取中文內(nèi)容。
代碼如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-598479.html
//壓縮
final zipFile = File("text.zip");
final archive = Archive();
var str="中文";
//這步是必須的
var encodeStr=utf8.encode(str);
//必須要為ArchiveFile.STORE
final archiveFile=ArchiveFile("test.txt",str.length,encodeStr,ArchiveFile.STORE);
archive.addFile(archiveFile);
final zipData = ZipEncoder().encode(archive);
zipFile.writeAsBytesSync(zipData!);
//解壓
ArchiveFile?
f=ZipDecoder().decodeBytes(zipFile.readAsBytesSync()).findFile("test.txt");
var content=f?.content;
// 解碼
print(utf8.decode(content));
到了這里,關(guān)于flutter 使用archive壓縮與解壓文件時出現(xiàn)中文亂碼的問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!