Экранирование не-ASCII символов (или как удалить спецификацию?) - PullRequest
4 голосов
/ 23 февраля 2010

Мне нужно создать текстовый файл ANSI из набора записей Access, который выводит в JSON и YAML. Я могу написать файл, но вывод получится с оригинальными символами, и мне нужно их избежать. Например, умлаут-O (ö) должен быть "\ u00f6".

Я думал, что кодирование файла как UTF-8 будет работать, но это не так. Однако, посмотрев снова на кодировку файла, если вы напишите «UTF-8 без BOM», то все работает.

Кто-нибудь знает, как либо

a) Пишите текст как UTF-8 без спецификации, или б) Написать в ANSI, но без символов ASCII?

Public Sub testoutput()

Set db = CurrentDb()

str_filename = "anothertest.json"
MyFile = CurrentProject.Path & "\" & str_filename
str_temp = "Hello world here is an ö"

fnum = FreeFile

Open MyFile For Output As fnum
Print #fnum, str_temp
Close #fnum

End Sub

Ответы [ 2 ]

6 голосов
/ 23 февраля 2010

... хорошо .... я нашел пример кода о том, как удалить спецификацию. Я бы подумал, что было бы возможно сделать это более элегантно, когда на самом деле пишу текст в первую очередь. Не берите в голову. Следующий код удаляет спецификацию.

(Это было первоначально отправлено Саймоном Педерсеном в http://www.imagemagick.org/discourse-server/viewtopic.php?f=8&t=12705)

' Removes the Byte Order Mark - BOM from a text file with UTF-8 encoding
' The BOM defines that the file was stored with an UTF-8 encoding.

Public Function RemoveBOM(filePath)

    ' Create a reader and a writer
            Dim writer, reader, fileSize
            Set writer = CreateObject("Adodb.Stream")
            Set reader = CreateObject("Adodb.Stream")

    ' Load from the text file we just wrote
            reader.Open
            reader.LoadFromFile filePath

    ' Copy all data from reader to writer, except the BOM
            writer.Mode = 3
            writer.Type = 1
            writer.Open
            reader.Position = 5
            reader.CopyTo writer, -1

    ' Overwrite file
            writer.SaveToFile filePath, 2

    ' Return file name
            RemoveBOM = filePath

    ' Kill objects
            Set writer = Nothing
            Set reader = Nothing
    End Function

Это может быть полезно для кого-то еще.

1 голос
/ 08 декабря 2016

Опоздал на игру, но я не могу быть единственным программистом, которому надоел мой импорт SQL, разбитый текстовыми файлами с маркером порядка байтов.Очень мало «вопросов по стеку, которые касаются проблемы - это один из самых близких», поэтому я публикую здесь ответ с перекрытием.

Я говорю «с перекрытием», потому что код ниже решает немного другую проблемудля вас - основная цель - написание файла схемы для папки с разнородным набором файлов - но сегмент обработки спецификаций четко обозначен.

Ключевая функциональность заключается в том, что мы перебираем все файлы '.csv' в папке и тестируем каждый файл с быстрым откусыванием первых четырех байтов: и мы только удаляем только маркер порядка байтовесли мы увидим

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

Итак, без дополнительной adodb, вот код:

Код утилизации спецификации для текстовых файловв файле schema.ini:

Public Sub SetSchema(strFolder As String)
On Error Resume Next 
' Write a Schema.ini file to the data folder.
' This is necessary if we do not have the registry privileges to set the ' correct 'ImportMixedTypes=Text' registry value, which overrides IMEX=1
' The code also checks for ANSI or UTF-8 and UTF-16 files, and applies a ' usable setting for CharacterSet ( UNICODE|ANSI ) with a horrible hack.
' OEM codepage-defined text is not supported: further coding is required
' ...And we strip out Byte Order Markers, if we see them - the OLEDB SQL ' provider for textfiles can't deal with a BOM in a UTF-16 or UTF-8 file
' Not implemented: handling tab-delimited files or other delimiters. The ' code assumes a header row with columns, specifies 'scan all rows', and ' imposes 'read the column as text' if the data types are mixed.
Dim strSchema As String Dim strFile As String Dim hndFile As Long Dim arrFile() As Byte Dim arrBytes(0 To 4) As Byte
If Right(strFolder, 1) <> "\" Then strFolder = strFolder & "\"
' Dir() is an iterator function when you call it with a wildcard:
strFile = VBA.FileSystem.Dir(strFolder & "*.csv")
Do While Len(strFile) > 0
hndFile = FreeFile Open strFolder & strFile For Binary As #hndFile Get #hndFile, , arrBytes Close #hndFile
strSchema = strSchema & "[" & strFile & "]" & vbCrLf strSchema = strSchema & "Format=CSVDelimited" & vbCrLf strSchema = strSchema & "ImportMixedTypes=Text" & vbCrLf strSchema = strSchema & "MaxScanRows=0" & vbCrLf
If arrBytes(2) = 0 Or arrBytes(3) = 0 Then ' this is a hack strSchema = strSchema & "CharacterSet=UNICODE" & vbCrLf Else strSchema = strSchema & "CharacterSet=ANSI" & vbCrLf End If
strSchema = strSchema & "ColNameHeader = True" & vbCrLf strSchema = strSchema & vbCrLf

' BOM disposal - Byte order marks confuse OLEDB text drivers:
If arrBytes(0) = &HFE And arrBytes(1) = &HFF _ Or arrBytes(0) = &HFF And arrBytes(1) = &HFE Then
hndFile = FreeFile Open strFolder & strFile For Binary As #hndFile ReDim arrFile(0 To LOF(hndFile) - 1) Get #hndFile, , arrFile Close #hndFile
BigReplace arrFile, arrBytes(0) & arrBytes(1), ""
hndFile = FreeFile Open strFolder & strFile For Binary As #hndFile Put #hndFile, , arrFile Close #hndFile Erase arrFile
ElseIf arrBytes(0) = &HEF And arrBytes(1) = &HBB And arrBytes(2) = &HBF Then
hndFile = FreeFile Open strFolder & strFile For Binary As #hndFile ReDim arrFile(0 To LOF(hndFile) - 1) Get #hndFile, , arrFile Close #hndFile BigReplace arrFile, arrBytes(0) & arrBytes(1) & arrBytes(2), ""
hndFile = FreeFile Open strFolder & strFile For Binary As #hndFile Put #hndFile, , arrFile Close #hndFile Erase arrFile
End If

strFile = "" strFile = Dir
Loop
If Len(strSchema) > 0 Then
strFile = strFolder & "Schema.ini"
hndFile = FreeFile Open strFile For Binary As #hndFile Put #hndFile, , strSchema Close #hndFile
End If

End Sub

Public Sub BigReplace(ByRef arrBytes() As Byte, ByRef SearchFor As String, ByRef ReplaceWith As String) On Error Resume Next
Dim varSplit As Variant
varSplit = Split(arrBytes, SearchFor) arrBytes = Join$(varSplit, ReplaceWith)
Erase varSplit
End Sub

Код будет проще понять, если вы знаете, что байтовый массив может быть назначен для VBA.String и наоборот.Функция BigReplace () - это хак, который обходит неэффективную обработку строк в VBA, особенно распределение: вы обнаружите, что большие файлы вызывают серьезные проблемы с памятью и производительностью, если вы делаете это любым другим способом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...