US-ASCII에서 UTF-8 (iconv)로 강제 인코딩
US-ASCII에서 UTF-8로 여러 파일을 트랜스 코딩하려고합니다.
이를 위해 iconv를 사용하고 있습니다.
iconv -f US-ASCII -t UTF-8 file.php > file-utf8.php
내 원본 파일은 US-ASCII로 인코딩되어 변환이 발생하지 않습니다. ASCII가 UTF-8의 하위 집합이기 때문에 분명히 발생합니다 ...
그리고 인용 :
ASCII가 아닌 문자가 도입 될 때까지 텍스트 파일이 다르게 나타날 필요가 없습니다.
진실. 파일에 ASCII가 아닌 문자를 도입하고 저장하면 Eclipse를 사용하면 파일 인코딩 (문자 집합)이 UTF-8로 전환됩니다.
제 경우에는 iconv가 파일을 UTF-8로 트랜스 코딩 하도록 강제 하고 싶습니다 . 비 ASCII 문자가 있는지 여부.
참고 : 그 이유는 내 PHP 코드 (비 ASCII 파일 ...)가 일부 비 ASCII 문자열을 처리하기 때문에 문자열이 제대로 해석되지 않기 때문입니다 (프랑스어).
Il à © tait une fois ... l' homme sà © rie animée mythique d' Albert
Barillé (Procidis), 1ère
...
편집하다
US-ASCII
- 인 -의 부분 집합UTF-8
(참조 네드의 대답 은 아래를)US-ASCII
파일 이 실제로 인코딩 됨을 의미합니다 .UTF-8
- 내 문제는 다른 곳에서 왔습니다
ASCII는 UTF-8의 하위 집합이므로 모든 ASCII 파일은 이미 UTF-8로 인코딩되어 있습니다. ASCII 파일의 바이트와 "UTF-8로 인코딩"의 결과 인 바이트는 정확히 동일한 바이트입니다. 그들 사이에는 차이가 없으므로 아무것도 할 필요가 없습니다.
문제는 파일이 실제로 ASCII가 아니라는 것 같습니다. 사용중인 인코딩을 확인하고 올바르게 트랜스 코딩해야합니다.
짧은 대답
file
파일 인코딩 만 추측하며 잘못 될 수 있습니다 (특히 특수 문자가 큰 파일에서 늦게 나타나는 경우).- 당신이 사용할 수있는
hexdump
비 7 비트 ASCII 텍스트의 바이트보고 및 인코딩이 무엇인지 스스로 결정하는 것이 일반적 인코딩 (ISO-8859- *, UTF-8)에 대한 코드 테이블에 대해 비교합니다. iconv
파일의 내용에 관계없이 지정한 입력 / 출력 인코딩을 사용합니다. 잘못된 입력 인코딩을 지정하면 출력이 왜곡됩니다.- 심지어 실행 후
iconv
,file
때문에하는 제한 방식에 어떤 변화를보고하지 않을 수 있습니다file
시도가 인코딩에서 추측. 구체적인 예는 내 긴 답변을 참조하십시오. - 7 비트 ASCII (일명 us-ascii)는 바이트 수준에서 utf-8 및 8 비트 ASCII 확장 (iso-8859- *)과 동일합니다. 따라서 파일에 7 비트 문자 만있는 경우 바이트 수준에서 모두 동일하므로 utf-8, iso-8859- * 또는 us-ascii라고 부를 수 있습니다. 파일에 7 비트 ASCII 범위를 벗어난 문자가있는 경우에만 utf-8 및 기타 인코딩 (이 컨텍스트에서)에 대해 이야기하는 것이 좋습니다.
긴 답변
나는 오늘 이것을 만났고 당신의 질문을 발견했습니다. 이 문제에 직면 한 다른 사람들을 돕기 위해 정보를 조금 더 추가 할 수 있습니다.
첫째, ASCII라는 용어가 과부하되어 혼란을 야기합니다.
7 비트 ASCII에는 128 자만 포함됩니다 (10 진수로 00-7F 또는 0-127). 7 비트 ASCII는 US-ASCII라고도합니다.
https://en.wikipedia.org/wiki/ASCII
UTF-8 인코딩은 처음 128 자에 대해 7 비트 ASCII와 동일한 인코딩을 사용합니다. 따라서 처음 128 자 범위의 문자 만 포함하는 텍스트 파일은 UTF-8 또는 7 비트 ASCII로 인코딩되었는지 여부에 관계없이 바이트 수준에서 동일합니다.
https://en.wikipedia.org/wiki/UTF-8#Codepage_layout
용어 확장 ASCII (또는 높은 ASCII는 ) 표준 일곱 비트 ASCII 문자와 추가 문자가 포함 된 8 비트 이상의 문자 인코딩을 의미합니다.
https://en.wikipedia.org/wiki/Extended_ASCII
ISO-8859-1 (일명 "ISO Latin 1")은 서유럽의 대부분의 문자를 다루는 특정 8 비트 ASCII 확장 표준입니다. 동유럽 언어와 키릴 어에 대한 다른 ISO 표준이 있습니다. ISO-8859-1에는 독일어 및 스페인어의 경우 Ö, é, ñ 및 ß와 같은 문자가 포함됩니다. "확장"은 ISO-8859-1이 7 비트 ASCII 표준을 포함하고 8 비트를 사용하여 문자를 추가 함을 의미합니다. 따라서 처음 128 자의 경우 바이트 수준에서 ASCII 및 UTF-8 인코딩 파일과 동일합니다. 그러나 처음 128자를 초과하는 문자를 처리하기 시작하면 더 이상 바이트 수준에서 UTF-8과 동일하지 않으며 "확장 ASCII"파일을 UTF-8로 인코딩하려면 변환을 수행해야합니다.
https://en.wikipedia.org/wiki/Extended_ASCII#ISO_8859_and_proprietary_adaptations
오늘 제가 배운 한 가지 교훈 file
은 파일의 문자 인코딩에 대한 올바른 해석을 항상 제공한다고 믿을 수 없다는 것 입니다.
https://en.wikipedia.org/wiki/File_%28command%29
이 명령은 파일이 무엇인지 (파일이 콘텐츠를 보는 경우)가 아니라 파일의 모양 만 알려줍니다. 내용과 일치하지 않는 파일에 매직 넘버를 넣어서 프로그램을 속이기 쉽습니다. 따라서 명령은 특정 상황 이외의 보안 도구로 사용할 수 없습니다.
file
파일에서 유형을 암시하는 매직 넘버를 찾지 만 이는 정확하지 않을 수 있으며 잘못된 것일 수 있습니다. file
또한 파일의 바이트를보고 문자 인코딩을 추측하려고합니다. 기본적으로 file
파일 유형과 인코딩을 추측하는 데 도움이되는 일련의 테스트가 있습니다.
내 파일은 큰 CSV 파일입니다. file
이 파일을 us-ascii로 인코딩 된 WRONG으로보고 합니다.
$ ls -lh
total 850832
-rw-r--r-- 1 mattp staff 415M Mar 14 16:38 source-file
$ file -b --mime-type source-file
text/plain
$ file -b --mime-encoding source-file
us-ascii
내 파일에는 움라우트가 있습니다 (예 : Ö). 7 비트가 아닌 첫 번째 ASCII는 파일에 100,000 줄이 넘을 때까지 표시되지 않습니다. 이것이 file
파일 인코딩이 US-ASCII가 아니라는 것을 깨닫지 못하는 이유라고 생각합니다 .
$ pcregrep -no '[^\x00-\x7F]' source-file | head -n1
102321:�
저는 Mac을 사용하고 있으므로 PCRE의 grep
. gnu grep을 사용하면 -P
옵션을 사용할 수 있습니다 . 또는 Mac에서 gnu grep을 얻기 위해 (homebrew 또는 기타를 통해) coreutils를 설치할 수 있습니다.
나는의 소스 코드를 파지 않았고 file
man 페이지는 텍스트 인코딩 감지에 대해 자세히 설명 file
하지 않지만 인코딩을 추측하기 전에 전체 파일을 보지 않는 것 같습니다.
내 파일의 인코딩이 무엇이든, 이러한 7 비트 ASCII가 아닌 문자는 문제를 해결합니다. 내 독일어 CSV 파일이 ;
분리되어 있고 단일 열 추출이 작동하지 않습니다.
$ cut -d";" -f1 source-file > tmp
cut: stdin: Illegal byte sequence
$ wc -l *
3081673 source-file
102320 tmp
3183993 total
노트 cut
오류를 내 "TMP"파일 라인 102321의 첫 번째 특수 문자 만 102,320 라인이 있는지 확인합니다.
이러한 비 ASCII 문자가 어떻게 인코딩되는지 살펴 보겠습니다. 7 비트가 아닌 첫 번째 ASCII를으로 덤프하고 hexdump
약간의 서식을 지정하고 개행 문자 ( 0a
)를 제거 하고 처음 몇 개만 가져옵니다.
$ pcregrep -o '[^\x00-\x7F]' source-file | head -n1 | hexdump -v -e '1/1 "%02x\n"'
d6
0a
또 다른 방법. 첫 번째 비 -7 비트 ASCII 문자가 102321 행의 85 위에 있다는 것을 알고 있습니다.이 행을 잡고 85 위에서 hexdump
시작하는 2 바이트를 취하 라고 말합니다 . 특수 문자 (비 -7 비트 ASCII)를 볼 수 있습니다. 문자는 "."로 표시되고 다음 바이트는 "M"입니다. 따라서 이것은 단일 바이트 문자 인코딩입니다.
$ tail -n +102321 source-file | head -n1 | hexdump -C -s85 -n2
00000055 d6 4d |.M|
00000057
두 경우 모두 특수 문자가로 표시되는 것을 볼 수 d6
있습니다. 이 문자는 독일어 문자 인 Ö이므로 ISO-8859-1에 포함되어야한다고 생각합니다. 확실히 "d6"이 일치하는 것을 볼 수 있습니다 ( https://en.wikipedia.org/wiki/ISO/IEC_8859-1#Codepage_layout ).
중요한 질문 ... 파일 인코딩을 확신하지 않고이 문자가 Ö인지 어떻게 알 수 있습니까? 답은 맥락입니다. 파일을 열고 텍스트를 읽은 다음 어떤 문자가 될지 결정했습니다. 내가 그것을 열면 문자 인코딩 (이 경우) 을 추측 하는 것보다 더 나은 작업을 수행 vim
하기 때문에 Ö로 표시됩니다 .vim
file
그래서 내 파일은 ISO-8859-1 인 것 같습니다. 이론적으로는 ISO-8859-1이 잘 맞는지 확인하기 위해 7 비트가 아닌 ASCII 문자의 나머지를 확인해야합니다. 파일을 쓸 때 프로그램이 단일 인코딩 만 사용하도록 강제하는 것은 없습니다. 디스크 (좋은 매너 제외).
확인을 건너 뛰고 전환 단계로 이동하겠습니다.
$ iconv -f iso-8859-1 -t utf8 source-file > output-file
$ file -b --mime-encoding output-file
us-ascii
흠. file
변환 후에도이 파일이 US-ASCII라는 메시지가 표시됩니다. hexdump
다시 확인해 봅시다 .
$ tail -n +102321 output-file | head -n1 | hexdump -C -s85 -n2
00000055 c3 96 |..|
00000057
확실히 변화. 2 바이트의 비 7 비트 ASCII (오른쪽에 "."로 표시됨)가 있고 2 바이트의 16 진수 코드는 이제 c3 96
. 살펴보면 이제 UTF-8이있는 것 같습니다 (c3 96은 UTF-8에서 Ö의 올바른 인코딩입니다) http://www.utf8-chartable.de/
그러나 file
여전히 우리 파일을 us-ascii
? 글쎄, 나는 이것이 file
전체 파일을 보지 않고 7 비트가 아닌 첫 번째 ASCII 문자가 파일 깊숙이 들어올 때까지 발생하지 않는다는 사실 로 거슬러 올라간다고 생각 합니다.
내가 사용합니다 sed
파일의 시작 부분에 Ö을 고수하고 어떻게되는지.
$ sed '1s/^/Ö\'$'\n/' source-file > test-file
$ head -n1 test-file
Ö
$ head -n1 test-file | hexdump -C
00000000 c3 96 0a |...|
00000003
좋아요, 움라우트가 있습니다. 인코딩은 c3 96 (utf-8)입니다. 흠.
동일한 파일에서 다른 움라우트를 다시 확인합니다.
$ tail -n +102322 test-file | head -n1 | hexdump -C -s85 -n2
00000055 d6 4d |.M|
00000057
ISO-8859-1. Oops! Just goes to show how easy it is to get the encodings screwed up.
Let's try converting our new test file with the umlaut at the front and see what happens.
$ iconv -f iso-8859-1 -t utf8 test-file > test-file-converted
$ head -n1 test-file-converted | hexdump -C
00000000 c3 83 c2 96 0a |.....|
00000005
$ tail -n +102322 test-file-converted | head -n1 | hexdump -C -s85 -n2
00000055 c3 96 |..|
00000057
Oops. That first umlaut that was UTF-8 was interpreted as ISO-8859-1 since that is what we told iconv
. The second umlaut is correctly converted from d6
to c3 96
.
I'll try again, this time I will use vim
to do the Ö insertion instead of sed
. vim
seemed to detect the encoding better (as "latin1" aka ISO-8859-1) so perhaps it will insert the new Ö with a consistent encoding.
$ vim source-file
$ head -n1 test-file-2
�
$ head -n1 test-file-2 | hexdump -C
00000000 d6 0d 0a |...|
00000003
$ tail -n +102322 test-file-2 | head -n1 | hexdump -C -s85 -n2
00000055 d6 4d |.M|
00000057
Looks good. Looks like ISO-8859-1 for new and old umlauts.
Now the test.
$ file -b --mime-encoding test-file-2
iso-8859-1
$ iconv -f iso-8859-1 -t utf8 test-file-2 > test-file-2-converted
$ file -b --mime-encoding test-file-2-converted
utf-8
Boom! Moral of the story. Don't trust file
to always guess your encoding right. Easy to mix encodings within the same file. When in doubt, look at the hex.
A hack (also prone to failure) that would address this specific limitation of file
when dealing with large files would be to shorten the file to make sure that special characters appear early in the file so file
is more likely to find them.
$ first_special=$(pcregrep -o1 -n '()[^\x00-\x7F]' source-file | head -n1 | cut -d":" -f1)
$ tail -n +$first_special source-file > /tmp/source-file-shorter
$ file -b --mime-encoding /tmp/source-file-shorter
iso-8859-1
Update
Christos Zoulas updated file
to make the amount of bytes looked at configurable. One day turn-around on the feature request, awesome!
http://bugs.gw.com/view.php?id=533 https://github.com/file/file/commit/d04de269e0b06ccd0a7d1bf4974fed1d75be7d9e
The feature was released in file
version 5.26.
Looking at more of a large file before making a guess about encoding takes time. However it is nice to have the option for specific use-cases where a better guess may outweigh additional time/io.
Use the following option:
−P, −−parameter name=value
Set various parameter limits.
Name Default Explanation
bytes 1048576 max number of bytes to read from file
Something like...
file_to_check="myfile"
bytes_to_scan=$(wc -c < $file_to_check)
file -b --mime-encoding -P bytes=$bytes_to_scan $file_to_check
...should do the trick if you want to force file
to look at the whole file before making a guess. Of course this only works if you have file
5.26 or newer.
I haven't built/tested the latest releases yet. Most of my machines currently have file
5.04 (2010)... hopefully someday this release will make it down from upstream.
So people say you can't and I understand you may be frustrated when asking a question and getting such an answer.
If you really want it to show in utf-8 instead of us-ascii then you need to do it in 2 steps.
first :
iconv -f us-ascii -t utf-16 yourfile > youfileinutf16.*
second:
iconv -f utf-16le -t utf-8 yourfileinutf16 > yourfileinutf8.*
then if you do a file -i you'll see the new charset is utf-8.
Hope it helps.
I think Ned's got the core of the problem -- your files are not actually ASCII. Try
iconv -f ISO-8859-1 -t UTF-8 file.php > file-utf8.php
I'm just guessing that you're actually using iso-8859-1, it is popular with most European languages.
There is no difference between US-ASCII and UTF-8, so no need to reconvert it. But here a little hint, if you have trouble with special-chars while recodeing.
Add //TRANSLIT after the source-charset-Parameter.
Example:
iconv -f ISO-8859-1//TRANSLIT -t UTF-8 filename.sql > utf8-filename.sql
This helps me on strange types of quotes, which are allways broke the charset reencode process.
Here's a script that will find all files matching a pattern you pass it, then converting them from their current file encoding to utf-8. If the encoding is us-ascii, then it will still show as us-ascii, since that is a subset of utf-8.
#!/usr/bin/env bash
find . -name "${1}" |
while read line;
do
echo "***************************"
echo "Converting ${line}"
encoding=$(file -b --mime-encoding ${line})
echo "Found Encoding: ${encoding}"
iconv -f "${encoding}" -t "utf-8" ${line} -o ${line}.tmp
mv ${line}.tmp ${line}
done
You can use file -i file_name
to check what exactly your original file format is.
Once you get that, you can do the following:
iconv -f old_format -t utf-8 input_file -o output_file
I accidentally encoded a file in UTF-7 and had a similar issue. When I typed file -i name.file
I would get charset=us-ascii
. iconv -f us-ascii -t utf-9//translit name.file
would not work since I've gathered UTF-7 is a subset of us-ascii, as is UTF-8.
To solve this I entered: iconv -f UTF-7 -t UTF-8//TRANSLIT name.file -o output.file
I'm not sure how to determine the encoding other than what others have suggested here.
ReferenceURL : https://stackoverflow.com/questions/11303405/force-encode-from-us-ascii-to-utf-8-iconv
'IT Share you' 카테고리의 다른 글
CSS를 통해 'semi-bold'글꼴을 설정하려면 어떻게해야합니까? (0) | 2021.01.10 |
---|---|
C ++에서 조합 생성 (0) | 2021.01.10 |
이미 인스턴스화 된 객체에 속성을 추가 할 수있는 이유는 무엇입니까? (0) | 2021.01.10 |
datatable jquery-테이블 헤더 너비가 본문 너비와 정렬되지 않음 (0) | 2021.01.10 |
Bash 자동화를 위해 명령 줄에서 Postgres 용 사용자를 만드는 방법 (0) | 2021.01.10 |