找回密码
 加入
搜索
查看: 17352|回复: 35

[系统综合] [已解决]如何判断字符串中含有ANSI编码不能保存的 Unicode 格式的字符

 火.. [复制链接]
发表于 2011-11-4 12:54:31 | 显示全部楼层 |阅读模式
本帖最后由 afan 于 2011-11-5 10:09 编辑

先运行以下这个简单的脚本
$str = BinaryToString('0x00A0', 3)
ClipPut($str)
Run('notepad.exe')
WinActivate('[CLASS:Notepad]', '')
Sleep(100)
Send('^v')
Send('^s')
在保存时会出现如下提示:
该文件含有 Unicode 格式的字符,当文件保存为 ANSI 编码的文本文件时,该字符将丢失。……

此时只能保存为U字头编码的文件才会不丢失字符。

如果需要判断编码的是“文件”,那可以使用 FileGetEncoding() 之类的简单判断。
但对于字符串,它不存在 BOM ,或者说是文件头信息,那又该如何判断呢?
尝试过用正则判断,但没找到相关的编码范围,只有放弃了。

请大家赐教,谢谢~
发表于 2011-11-4 14:21:38 | 显示全部楼层
有个StringisAscII函数
Checks if a string contains only ASCII characters in the range 0x00 - 0x7f (0 - 127).

$str = BinaryToString('0x00A0', 3)
        
        $result= StringIsASCII($str) 
        if $result=1 then
                MsgBox(0,"",StringIsASCII($str))
        
ClipPut($str)
Run('notepad.exe')
WinActivate('[CLASS:Notepad]', '')
Sleep(100)
Send('^v')
Send('^s')
        
Else
        $nes=BinaryToString('0x00A0',4 )
        ClipPut($nes)
Run('notepad.exe')
WinActivate('[CLASS:Notepad]', '')
Sleep(100)
Send('^v')
Send('^s')
EndIf


提示是没有了,但貌似粘贴的一个空

评分

参与人数 1金钱 +30 贡献 +1 收起 理由
afan + 30 + 1 sf~

查看全部评分

 楼主| 发表于 2011-11-4 14:29:41 | 显示全部楼层
回复 2# amxi


    呵呵,这个只是检测字符串是否包含 0x00 到 0x7f (0-127)之间的 ASCII 字符,这个范围并不是ANSI编码的全部范围。比如一个双字节字符,不属于该检测范围,但是保存为ANSI编码是没有问题的。

感谢参与讨论~
发表于 2011-11-4 14:44:29 | 显示全部楼层
else下面这句
  $nes=BinaryToString('0x00A0',3)  ;4改回3. utf16
,虽然也提示:[]quote]
该文件含有 Unicode 格式的字符,当文件保存为 ANSI 编码的文本文件时,该字符将丢失。……[/quote]
直接点确定的话没有让你选择编码,直接可以保存的.

ansi  unicode哎,还不到那程度.
 楼主| 发表于 2011-11-4 14:47:34 | 显示全部楼层
回复 4# amxi


    直接保存当然可以,不过已经丢失字符了。你将保存的文件重新打开就会发现,显示的是个问号~
 楼主| 发表于 2011-11-4 14:54:17 | 显示全部楼层
之所以作此判断,是因为在将字符串保存为文件时可以使用 FileOpen() 选择编码模式。
虽然都直接用 Unicode 格式保存不会有问题,都如果是 ANSI 编码可以保存的还是尽量用ANSI编码,特别是保存的是诸如 .au3 的脚本文件。
发表于 2011-11-4 15:12:27 | 显示全部楼层
额,帮助文档里推荐脚本的编码是用utf8.

你这个编码问题太深了,潜不到了.
 楼主| 发表于 2011-11-4 15:21:12 | 显示全部楼层
额,帮助文档里推荐脚本的编码是用utf8..
amxi 发表于 2011-11-4 15:12



    ANSI 或 UTF8 都好说,只要不保存为其它的Unicode UTF16 就好~
发表于 2011-11-4 18:10:25 | 显示全部楼层
#include <File.au3>
#include <winapi.au3>

$filename = "out.txt"
$CODE = _GetFileCode($filename)
MsgBox(0, 0, $CODE)

Func _GetFileCode($file)
        Local $nBytes
        $tBuffer = DllStructCreate("byte[" & 2 & "]")
        $hFile = _WinAPI_CreateFile($file, 2, 2)
        _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer), 2, $nBytes)
        _WinAPI_CloseHandle($hFile)
        $sText = DllStructGetData($tBuffer, 1)
        Switch $sText
                Case "0xEFBB"
                        Return "UTF-8"
                Case "0XFEFF"
                        Return "Unicode big endian"
                Case "0XFEFE"
                        Return "Unicode"
                Case Else
                        Return "ANSI"
        EndSwitch
EndFunc   ;==>_GetFileCode

评分

参与人数 1金钱 +30 贡献 +1 收起 理由
afan + 30 + 1 不是指文件哦 :)

查看全部评分

 楼主| 发表于 2011-11-4 20:47:57 | 显示全部楼层
本帖最后由 afan 于 2011-11-4 20:52 编辑
3mile 发表于 2011-11-4 18:10



    3m 貌似没弄懂我的意思哦~ 我是说的检测还未成为“文件”的“字符串”~ 一楼说明了,如果是文件,内置函数 FileGetEncoding() 就可以检测。呵呵~

简单的说,判断以下字符串变量 $str 能否保存为 ANSI编码的文本,而不丢失字符~
$str = BinaryToString('0x00A0', 3)
发表于 2011-11-4 21:24:36 | 显示全部楼层
回复 10# afan


    管它有没有,直接转换就可以了。实际应用中就是这样

#Include <WinAPI.au3>

$str = BinaryToString('0x00A0', 3)
$str = _WinAPI_WideCharToMultiByte($str, 65001)
MsgBox(0,0,$str)

评分

参与人数 1金钱 +30 收起 理由
afan + 30

查看全部评分

 楼主| 发表于 2011-11-4 21:37:52 | 显示全部楼层
回复  afan


    管它有没有,直接转换就可以了。实际应用中就是这样
happytc 发表于 2011-11-4 21:24



    如果是不管它有没有就直接转换,如果1000个字符中只有1个需要转换那岂不是很不划算~ 而且也不知道转换得对否,貌似此例中的转换就是错误的。
转换还不如直接就用UTF8保存~
发表于 2011-11-4 22:20:48 | 显示全部楼层
如果是不管它有没有就直接转换,如果1000个字符中只有1个需要转换那岂不是很不划算~ 而且也不知道 ...
afan 发表于 2011-11-4 21:37


其实我想说的是,你这个命题本身就是个伪命题,没有 “字符串包含Unicode字符的说法”。不可能一个字符串包含Ansi和unicode两种编码,除非是自己写内存。

所以我才说,直接转。

估计你认为象:$Str = 'hello/你好/&#1575;&#1604;&#1587;&#1604;&#1575;&#1605; &#1593;&#1604;&#1610;&#1603;&#1605;'  (分别是英语/中文/阿拉伯语的‘你好’)中的'hello'是ANSI的,别的是Unicode 的
 楼主| 发表于 2011-11-4 22:28:28 | 显示全部楼层
其实我想说的是,你这个命题本身就是个伪命题,没有 “字符串包含Unicode字符的说法”。不可能一个字符 ...
happytc 发表于 2011-11-4 22:20



    看我三楼的回复,你还会提出我所指的“'hello'是ANSI的,别的是Unicode 的”这个问题吗?
判断中文,甚至分出简体、繁体、符号我都可以用正则轻松实现~
发表于 2011-11-4 23:08:15 | 显示全部楼层
本帖最后由 happytc 于 2011-11-4 23:23 编辑

回复 14# afan

所以问题就简化为:一个宽(unicode)字符串,若其中一个字符在 CodePage 制定的代码页中没有对应的表示时,怎么检测出来?
其实我上面说到的函数WideCharToMultiByte的参数中
int WideCharToMultiByte(
  __in   UINT CodePage,
  __in   DWORD dwFlags,
  __in   LPCWSTR lpWideCharStr,
  __in   int cchWideChar,
  __out  LPSTR lpMultiByteStr,
  __in   int cbMultiByte,
  __in   LPCSTR lpDefaultChar,
  __out  LPBOOL lpUsedDefaultChar
);
http://msdn.microsoft.com/en-us/library/windows/desktop/dd374130(v=vs.85).aspx)
在这函数中的后两个参数就是干这个活的:若一个字符在 CodePage 制定的代码页中没有对应的表示时,WideCharToMultiByte 就会使用后两个参数,也就是在遇到一个不能转换的字符时,函数便使用 pDefaultChar 参数指向的字符。如果这个参数指向为 NULL ,函数就会使用一个默认的字符。于是也就可以用这个特性检测出unicode字符串中不能转为ansi的字符

__out  LPBOOL lpUsedDefaultChar // 宽字符字符串中,如果至少有一个字符不能转换为对应的多字节形式,函数就会把这个变量设为 TRUE 。如果所有字符都能成功转换,就会把这个变量设为 FALSE。 通常将此函数传入 NULL 值。

评分

参与人数 1贡献 +2 收起 理由
afan + 2

查看全部评分

您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-12-24 02:42 , Processed in 0.103449 second(s), 31 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表