delphi打开unicode文件的问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了delphi打开unicode文件的问题相关的知识,希望对你有一定的参考价值。
有一个unicode文件用了多种方法都无法正常打开显示,具体问题如下:1、文件在windows系统里显示30个字节,但是在ultraedit里面看到不止30字节2、在delphi里面用tfilestream,tmemorystream读取都是30字节,而且读取的文件不完整,和在ultraedit里看到的不一样,头部的#FF#FE就没有读出来。两种方法读出来显示都是乱码3、用memo1.lines.loadfromfile读取出来也是显示乱码求一段代码可以在delphi XE3或者XE10下面运行,把文字正常显示在memo框里
文字正常显示应该是:
"type":"egg","city":"宣城"
经实际输入截图中的数据,如下图:
并编写代码测试(delphi XE7 + Win10):
begin
Memo1.Lines.LoadFromFile(\'d:\\编辑2.txt\');
end;
测试结果如图:
从测试结果看,能正确读取并显示数据。
据分析,截图中的文本需要以 UTF-16 LE BOM 编码格式存储。
补充:
delphi Xe 版本以上,都使用 unicode 作为常用字符编码支持,TStrings 类的 LoadFromFile 和 LoadFromStream 都有重载的版本:
普通版本:
procedure TStrings.LoadFromStream(Stream: TStream);
重载版本:
procedure TStrings.LoadFromFile(const FileName: string; Encoding: TEncoding);
重载版本,增加了一个 Endcoding 参数,用于指示读取数据的编码格式。
TEncoding 可以使用以下的编码格式:
在本问题中,你可以尝试使用 Unicode 和 BigEndianUnicode 编码来加载读取数据。
// Unicode文件写入函数
procedure SaveUnicodeFile(const FileName:string; const S: string; WriteHeader: Boolean = True);
var
MemStream: TMemoryStream;
HeaderStr: string;
WStr: WideString;
begin
if S = '' then exit;
MemStream := TMemoryStream.Create;
try
if WriteHeader then
begin
HeaderStr := #$FF#$FE;
MemStream.Write(HeaderStr[1], 2);
end;
WStr := WideString(S);
MemStream.Write(WStr[1], Length(WStr)*2);
MemStream.Position := 0;
MemStream.SaveToFile(FileName);
finally
MemStream.Free;
end;
end;
// Unicode文件读取函数
function LoadUnicodeFile(const FileName: string; ReadHeader: Boolean = True): string;
var
MemStream: TMemoryStream;
FlagStr: String;
WStr: WideString;
begin
Result := '';
if not FileExists(FileName) then Exit;
MemStream := TMemoryStream.Create;
try
MemStream.LoadFromFile(FileName);
if ReadHeader then
begin
SetLength(FlagStr, 2);
MemStream.Read(FlagStr[1], 2);
if FlagStr = #$FF#$FE then
begin
SetLength(WStr, (MemStream.Size-2) div 2);
MemStream.Read(WStr[1], MemStream.Size - 2);
end;
end else
begin
SetLength(WStr, MemStream.Size div 2);
MemStream.Read(WStr[1], MemStream.Size);
end;
Result := AnsiString(WStr);
finally
MemStream.Free;
end;
end;追问
请教一下,您的截图中设置编码的那个画面是在哪一个软件里操作的?我试一下
追答这不是截图,这是文本编码(delphi的函数),可以直接复制使用。
后面的函数直接将unicode文件转化为ansistring串返回。
我想问的是标题写着编码设置,下面有多种编码可以选择的那张图。感谢
追答看看楼下的补充
本回答被提问者采纳Django创建包含Unicode的CSV文件,可以直接用Excel打开
【中文标题】Django创建包含Unicode的CSV文件,可以直接用Excel打开【英文标题】:Django create CSV file that contains Unicode and can be opened directly with Excel 【发布时间】:2012-06-06 10:48:06 【问题描述】:我想通过 Django 创建一个包含 unicode 数据(希腊字符)的 CSV 文件,并且我希望它可以直接从 MS Excel 打开。在其他地方我读到了 unicodecsv 库,我决定使用它。所以,这是我的看法;
def get_csv(请求,id): 响应 = HttpResponse(mimetype='text/csv') response['Content-Disposition'] = '附件;文件名=csv.csv' writer = unicodecsv.writer(response, encoding='utf-16"') writer.writerow(['第二行', 'A', 'B', 'C', '"测试"', "ελληνικά"]) 返回响应现在,除了utf-16,我真的尝试了everything在writer的encoding参数中,包括utf-8, utf-8-sig, utf-8-le, utf-16 -le,也许还有其他人。每次我用 excel 打开文件时,我总是在希腊字符应该出现的地方看到垃圾。
Notepad++ 能够毫无问题地打开文件。我做错了什么?
更新:这是我在 jd 回答后尝试的:
导入 csv 响应 = HttpResponse(mimetype='text/csv') response['Content-Disposition'] = '附件;文件名=test.csv' response.write(u'\ufeff'.encode('utf8')) writer = csv.writer(response, delimiter=';' , dialect='excel') writer.writerow(['第二行', 'A', 'B', 'C', '"测试"', "ελληνικά"]) 返回响应仍然没有运气 - 现在我也可以在 Excel 中看到 BOM(作为抓取) - 我也尝试使用 unicodecsv 和其他一些选项,但再次没有任何效果:(
更新 2: 我在 dda 的提议后尝试了这个:
writer = unicodecsv.writer(response, delimiter=';' , dialect='excel') writer.writerow(codecs.BOM_UTF16_LE) writer.writerow([ (u'ελληνικά').decode('utf8').encode('utf_16_le')])仍然没有运气:(这是我得到的错误:
/csv/559 处的 UnicodeEncodeError “ascii”编解码器无法对位置 0-7 中的字符进行编码:序数不在范围内(128)更新 3: 我快疯了。为什么这么难???这是另一个尝试:
response.write(codecs.BOM_UTF16_LE) writer = unicodecsv.writer(response, delimiter=';' , lineterminator='\n', dialect='excel', ) writer.writerow('ελληνικ') writer.writerow([ ('ελληνικά').decode('utf8').encode('utf_16_le')]) #A writer.writerow([ ('ελληνικά2').decode('utf8').encode('utf_16_le'), ('ελληνικά2').decode('utf8').encode('utf_16_le') ]) #B这是 Excel 的内容:
㯎㮵㯎㮻㯎㮻㯎㮷㯎㮽㯎㮹㯎ελληνικά딊묃묃뜃봃뤃먃갃㈃딻묃묃뜃봃뤃먃갃㈃所以我得到了一些带有#A 行的希腊字符。但是 B 行,完全一样的并没有给我生成希腊字符 $^#$#^$#$#^ @@%$#^#^$#$ 请帮忙!
【问题讨论】:
您在 MacOS 上使用 Excel 吗? This SO answer 是我发现 BOM 技巧的地方,显然它不适用于 MacOS 的 Excel。 不,我正在使用 Excel for Windows :( (u'ελληνικά').decode('utf8').encode('utf_16_le'):你不应该解码一个 unicode 字符串。您只能对它们进行编码。 jd 你是对的,这就是为什么我删除了字符串前面的 'u'... 但是我仍然遇到问题,正如你在更新 3 中看到的那样 :( 请不要再为这个问题烦恼了,我最终使用了 xlwt !我也向大家推荐 - 我在 5 分钟内就搞定了!!! 【参考方案1】:使用 Python 的 csv
模块,您可以编写一个 UTF-8 文件,如果您在文件开头放置 BOM,Excel 将正确读取该文件。
with open('myfile.csv', 'wb') as f:
f.write(u'\ufeff'.encode('utf8'))
writer = csv.writer(f, delimiter=';', lineterminator='\n', quoting=csv.QUOTE_ALL, dialect='excel')
...
同样适用于unicodecsv
。我想您可以将 BOM 直接写入 HttpResponse
对象,如果没有,您可以使用 StringIO
先写入文件。
编辑:
这里有一些示例代码,它使用非 ASCII 字符编写 UTF-8 CSV 文件。为简单起见,我将 Django 排除在外。我可以在 Excel 中读取该文件。
# -*- coding: utf-8 -*-
import csv
import os
response = open(os.path.expanduser('~/utf8_test.csv'), 'wb')
response.write(u'\ufeff'.encode('utf8'))
writer = csv.writer(response, delimiter=';' , dialect='excel')
writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', u"ελληνικά".encode('utf8')])
response.close()
【讨论】:
好吧,我尝试了完全相同的代码,但我无法读取文件:(这怎么可能?我已经将它保存在 UTF-8 w/o BOM .py 中。我真的要疯了吗? ??? 当我用记事本++打开这个文件时它很好......这是我在Excel 2003中看到的内容:ο»Ώ第二行A B C“测试”ελληνικά 它对我不起作用。我在 Mac OS X 上使用 Office。不过,OpenOffice 可以毫无问题地打开文件。【参考方案2】:我一直无法在 Excel 中打开 UTF-8 编码 (CSV) 文件。我设法正确导入 Excel 文件的唯一方法是使用 UTF-16LE。 YMMV。
编辑
第一
writer.writerow(codecs.BOM_UTF16_LE)
然后(根据需要多次;str 是要编码和写入的字符串)
writer.writerow(str.decode('utf8').encode('utf_16_le'))
【讨论】:
我不关心文件的实际编码。那么,如何输出以 UTF-16LE 编码的文件并能够用 excel 读取呢?以上是关于delphi打开unicode文件的问题的主要内容,如果未能解决你的问题,请参考以下文章
delphi文件默认的编码方式为utf-8,有没有办法设为Unicode