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):

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.LoadFromFile(\'d:\\编辑2.txt\');
end;

测试结果如图:



从测试结果看,能正确读取并显示数据。

据分析,截图中的文本需要以 UTF-16 LE BOM 编码格式存储。

补充:

delphi Xe 版本以上,都使用 unicode 作为常用字符编码支持,TStrings 类的 LoadFromFile 和 LoadFromStream 都有重载的版本:

普通版本:

procedure TStrings.LoadFromFile(const FileName: string);
procedure TStrings.LoadFromStream(Stream: TStream);


重载版本:

procedure TStrings.LoadFromStream(Stream: TStream; Encoding: TEncoding);
procedure TStrings.LoadFromFile(const FileName: string; Encoding: TEncoding);

重载版本,增加了一个 Endcoding 参数,用于指示读取数据的编码格式。

TEncoding 可以使用以下的编码格式:


在本问题中,你可以尝试使用 Unicode 和 BigEndianUnicode 编码来加载读取数据。

参考技术A 这是转自网上的代码,你可以试试:

// 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-8Unicode格式文本文件

delphi文件默认的编码方式为utf-8,有没有办法设为Unicode

为啥记事本每次保存都说该文件含有unicode格式的字符?

delphi 中文奇数乱码

在 Delphi 2009 的 Rave Reports 中显示 unicode 文本

PHP字符串中的Unicode字符