1 (изменено: stealzy, 2017-03-15 15:45:35)

Тема: AHK: Сохранение файла с BOM

Данный скрипт (сохраненный в UTF-8 с BOM) успешно переписывает себя, но BOM теряет, соответственно, при последующих запусках, интерпретатор считает что кодировка CP12xx. Запускать дважды.

file := FileOpen(A_ScriptFullPath, "r")
encoding := file.Encoding
scriptContent := file.Read()
file.Close()

MsgBox Кодировка согласно свойству .Encoding`n%encoding%
MsgBox % GetFileBOM(A_ScriptFullPath)
GetFileBOM(file) {
  FileRead,text,*c %file%
  If (0xBFBBEF=NumGet(&text,"UInt") & 0xFFFFFF)
    Return "UTF-8 BOM"
  else if (0xFFFE=NumGet(&text,"UShort") || 0xFEFF=NumGet(&text,"UShort"))
    Return "UTF-16 BOM"
  FileGetSize,size,%file%
  Return StrLen(StrGet(&text,"UTF-8"))=size?"ANSI":"UTF-8 no BOM"
}

file := FileOpen(A_ScriptFullPath, "w")
file.Encoding := encoding
file.Write(scriptContent)
file.Close()

В справке по FileOpen() написано:

When a UTF-8 or UTF-16 file is created, a byte order mark is written to the file unless Encoding (or A_FileEncoding if Encoding is omitted) contains "UTF-8-RAW" or "UTF-16-RAW".

Почему-то в моем примере BOM не записывается.
Пока на ум ничего не приходит, разве что при сохранении добавлять в начало Hex-содержимого файла .

2 (изменено: teadrinker, 2017-03-16 12:12:08)

Re: AHK: Сохранение файла с BOM

При открытии файла с BOM указатель переносится сразу за него, и, соответственно, BOM в переменную scriptContent не попадает.

When a file containing a UTF-8 or UTF-16 byte order mark (BOM) is opened with read access, the BOM is excluded from the output by positioning the file pointer after it. Therefore, File.Position may report 3 or 2 immediately after opening the file.

Вот так сработает:

file := FileOpen(A_ScriptFullPath, "r")
MsgBox, % file.Pos
file.Pos := 0
encoding := file.Encoding
scriptContent := file.Read()
file.Close()

MsgBox % encoding

file := FileOpen(A_ScriptFullPath, "w")
file.Encoding := encoding
file.Write(scriptContent)
file.Close()
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3 (изменено: stealzy, 2017-03-15 21:08:17)

Re: AHK: Сохранение файла с BOM

В таком случае BOM попадает в MsgBox, хоть его там и не видно,
но если совершать операции с текстом, он может мешаться.
Получение текста без BOM (раскомментировать):

file := FileOpen(A_ScriptFullPath, "r")
;If (file.Pos <> 0) { ; BOM
	file.Pos := 0 ; for take BOM
	;BOM := file.Read(1) ; now pointer file.Pos = 3 or 2 again :-)
;}
encoding := file.Encoding
scriptContent := file.Read()
file.Close()

MsgBox % SubStr(scriptContent, 1, 4) = "file"

file := FileOpen(A_ScriptFullPath, "w")
file.Encoding := encoding
file.Write(BOM NewScriptContent)
file.Close()

4 (изменено: KusochekDobra, 2017-03-16 16:01:22)

Re: AHK: Сохранение файла с BOM

Привет. Вы забыли кодировку указать при записи:


file := FileOpen(A_ScriptFullPath, "r")
encoding := file.Encoding
scriptContent := file.Read()
file.Close()

MsgBox Кодировка согласно свойству .Encoding`n%encoding%
MsgBox % GetFileBOM(A_ScriptFullPath)
GetFileBOM(file) {
  FileRead,text,*c %file%
  If (0xBFBBEF=NumGet(&text,"UInt") & 0xFFFFFF)
    Return "UTF-8 BOM"
  else if (0xFFFE=NumGet(&text,"UShort") || 0xFEFF=NumGet(&text,"UShort"))
    Return "UTF-16 BOM"
  FileGetSize,size,%file%
  Return StrLen(StrGet(&text,"UTF-8"))=size?"ANSI":"UTF-8 no BOM"
}

file := FileOpen(A_ScriptFullPath, "w","UTF-8")
file.Encoding := encoding
file.Write(scriptContent)
file.Close()

Если это указывать явно, то проблемы не будет. Или вместо этого добавить в начало файла строку:


FileEncoding, UTF-8

5 (изменено: stealzy, 2017-03-16 22:58:59)

Re: AHK: Сохранение файла с BOM

Спасибо, но кодировку я не забывал - file.Encoding := encoding. И кстати, честное UTF-8 получается. Без BOM :^).
Я запостил свой велосипед по спасению BOM буржуям, и сам lexikos ответил мне, что для этого можно указывать кодировку в параметрах FileOpen().
Сейчас так и сделал:

file := FileOpen(A_ScriptFullPath, "r")
encoding := file.Encoding
scriptContent := file.Read()
; file.Close() ; it is not necessary

MsgBox % "Я" . (SubStr(scriptContent, 1, 4) = "file")

file := FileOpen(A_ScriptFullPath, "w", encoding)
file.Write(scriptContent)
file.Close()

6 (изменено: KusochekDobra, 2017-03-17 02:28:38)

Re: AHK: Сохранение файла с BOM

В сущности, я Вам то же самое, что и Отец всея Autohotkey написал(это даже в справке есть). Если посмотреть содержимое тега "code" на предмет сравнения с примером из поста №1, обозначенный момент можно заметить. Разница только в том, что в Вашем последнем примере, получаете кодировку исходника, чтобы сообщить её в процедуру записи, которую, Вы вначале действительно не забыли, но описали несколько не в том месте, для того чтобы получать ожидаемый результат, о согласии с чем так же свидетельствует отсутствие этой строки в Вашем, последнем примере.

Строка же:


FileEncoding, UTF-8

устанавливает нужную кодировку в качестве дефолтной и если предполагается пользовать её повсеместно, это избавляет от необходимости сообщать её соответствующим процедурам(о чём так же упомянуто в справке). А ещё, он Вам на своём "буржуйском" приводил и другой пример, что если вы собираетесь реализовать принцип, который, вероятно, демонстрирует Ваш сценарий, то не нужно не только закрывать файл, но и вновь его открывать. Контент файла у Вас уже есть, производите его модификацию согласно условиям, сообщаете объекту новый размер равный нулю и пишете изменённый контент обратно в объект:


file := FileOpen(A_ScriptFullPath, "r")
encoding := file.Encoding
scriptContent := file.Read()
; file.Close() ; it is not necessary

MsgBox % "Я" . (SubStr(scriptContent, 1, 4) = "file")

;file := FileOpen(A_ScriptFullPath, "w", encoding)
file.Length := 0
file.Write(scriptContent)
file.Close()

Что так же справедливо и для Вашего первого примера:


file := FileOpen(A_ScriptFullPath, "r")
encoding := file.Encoding
scriptContent := file.Read()
;file.Close()

MsgBox Кодировка согласно свойству .Encoding`n%encoding%
MsgBox % GetFileBOM(A_ScriptFullPath)
GetFileBOM(file) {
  FileRead,text,*c %file%
  If (0xBFBBEF=NumGet(&text,"UInt") & 0xFFFFFF)
    Return "UTF-8 BOM"
  else if (0xFFFE=NumGet(&text,"UShort") || 0xFEFF=NumGet(&text,"UShort"))
    Return "UTF-16 BOM"
  FileGetSize,size,%file%
  Return StrLen(StrGet(&text,"UTF-8"))=size?"ANSI":"UTF-8 no BOM"
}

;file := FileOpen(A_ScriptFullPath, "w","UTF-8")
;file.Encoding := encoding
file.Length:=0
file.Write(scriptContent)
file.Close()

7 (изменено: stealzy, 2017-03-17 02:54:51)

Re: AHK: Сохранение файла с BOM

А вы реально пробовали писать в файл, открытый для чтения? Я вот пробовал, однажды.
Вы так убедительно написали, что сейчас попробовал еще раз :-).

8

Re: AHK: Сохранение файла с BOM

И то верно. Сам же пользуюсь постоянно. Иногда полезно наговорить херни, в обществе тех, кто умеет наиболее болезненно вернуть беседу в нужное русло. Закрепляет материал. Благодарю.