Có một câu hỏi thường gặp nhất, và vấn đề này là mơ hồ đối với tôi và vì tôi không biết nhiều về nó.Cách hiệu quả để tìm Mã hóa của bất kỳ tệp nào
Nhưng tôi muốn có cách rất chính xác để tìm tệp Encoding. Chính xác như Notepad ++.
Có một câu hỏi thường gặp nhất, và vấn đề này là mơ hồ đối với tôi và vì tôi không biết nhiều về nó.Cách hiệu quả để tìm Mã hóa của bất kỳ tệp nào
Nhưng tôi muốn có cách rất chính xác để tìm tệp Encoding. Chính xác như Notepad ++.
Thuộc tính StreamReader.CurrentEncoding
hiếm khi trả về mã hóa tệp văn bản chính xác cho tôi. Tôi đã có thành công lớn hơn xác định endianness của một tập tin, bằng cách phân tích dấu ấn thứ tự byte (BOM):
/// <summary>
/// Determines a text file's encoding by analyzing its byte order mark (BOM).
/// Defaults to ASCII when detection of the text file's endianness fails.
/// </summary>
/// <param name="filename">The text file to analyze.</param>
/// <returns>The detected encoding.</returns>
public static Encoding GetEncoding(string filename)
{
// Read the BOM
var bom = new byte[4];
using (var file = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
file.Read(bom, 0, 4);
}
// Analyze the BOM
if (bom[0] == 0x2b && bom[1] == 0x2f && bom[2] == 0x76) return Encoding.UTF7;
if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf) return Encoding.UTF8;
if (bom[0] == 0xff && bom[1] == 0xfe) return Encoding.Unicode; //UTF-16LE
if (bom[0] == 0xfe && bom[1] == 0xff) return Encoding.BigEndianUnicode; //UTF-16BE
if (bom[0] == 0 && bom[1] == 0 && bom[2] == 0xfe && bom[3] == 0xff) return Encoding.UTF32;
return Encoding.ASCII;
}
Như một mặt lưu ý, bạn có thể muốn thay đổi dòng cuối cùng của phương pháp này để trở Encoding.Default
thay thế, do mã hóa cho trang mã ANSI hiện tại của hệ điều hành được trả về theo mặc định.
+1. Điều này làm việc cho tôi quá (trong khi detectEncodingFromByteOrderMarks không). Tôi đã sử dụng "FileStream mới (tên tệp, FileMode.Open, FileAccess.Read)" để tránh một IOException vì tệp chỉ đọc. – Polyfun
điều này chắc chắn là câu trả lời đúng, câu trả lời chính xác không hoạt động đối với tôi – sebagomez
Các tệp UTF-8 có thể không có BOM, trong trường hợp này nó sẽ trả lại ASCII không chính xác. – user626528
tôi muốn thử các bước sau:
1) Kiểm tra nếu có một Byte Order Mark
2) Kiểm tra xem tập tin có giá trị UTF8
3) Sử dụng các địa phương "ANSI "codepage (ANSI như Microsoft định nghĩa nó)
Bước 2 hoạt động vì hầu hết các chuỗi không ASCII trong các mã khác mà UTF8 không hợp lệ UTF8.
Điều này có vẻ giống như câu trả lời đúng hơn, vì câu trả lời khác không phù hợp với tôi. Người ta có thể làm điều đó với File.OpenRead và .Read-ing vài byte đầu tiên của tập tin. – user420667
Bước 2 là một bó toàn bộ công việc lập trình để kiểm tra các mẫu bit. – Nyerguds
@Nyerguds Cách tiếp cận lười biếng là cố phân tích cú pháp dưới dạng UTF-8 và khởi động lại từ đầu khi bạn gặp lỗi giải mã. Một chút xấu xí (ngoại lệ cho luồng điều khiển) và tất nhiên việc phân tích cú pháp cần phải có tác dụng phụ miễn phí. – CodesInChaos
Các mã sau hoạt động tốt đối với tôi, bằng cách sử dụng lớp StreamReader
:
using (var reader = new StreamReader(fileName, defaultEncodingIfNoBom, true))
{
reader.Peek(); // you need this!
var encoding = reader.CurrentEncoding;
}
Bí quyết là sử dụng Peek
cuộc gọi, nếu không, .NET đã không được thực hiện bất cứ điều gì (và nó đã không đọc lời mở đầu , BOM). Tất nhiên, nếu bạn sử dụng bất kỳ cuộc gọi nào khác ReadXXX
trước khi kiểm tra mã hóa, nó cũng hoạt động.
Nếu tệp không có BOM, khi đó mã hóa defaultEncodingIfNoBom
sẽ được sử dụng. Ngoài ra còn có một StreamReader mà không có phương pháp này quá tải (trong trường hợp này, mặc định (ANSI) mã hóa sẽ được sử dụng như defaultEncodingIfNoBom), nhưng tôi recommand để xác định những gì bạn xem xét mã hóa mặc định trong bối cảnh của bạn.
Tôi đã thử nghiệm thành công với các tệp có BOM cho UTF8, UTF16/Unicode (LE & BE) và UTF32 (LE & BE). Nó không hoạt động đối với UTF7.
Tôi lấy lại những gì được đặt làm mã hóa mặc định. Tôi có thể bị mất một cái gì đó? – Rama
@DRAM - điều này có thể xảy ra nếu tệp không có BOM –
Cảm ơn @Simon Mourier. Tôi dint mong đợi pdf của tôi/bất kỳ tập tin sẽ không có bom. Liên kết này http://stackoverflow.com/questions/4520184/how-to-detect-the-character-encoding-of-a-text-file có thể hữu ích cho những người cố gắng phát hiện mà không cần bom. – Rama
Nhìn vào đây để C#
https://msdn.microsoft.com/en-us/library/system.io.streamreader.currentencoding%28v=vs.110%29.aspx
string path = @"path\to\your\file.ext";
using (StreamReader sr = new StreamReader(path, true))
{
while (sr.Peek() >= 0)
{
Console.Write((char)sr.Read());
}
//Test for the encoding after reading, or at least
//after the first read.
Console.WriteLine("The encoding used was {0}.", sr.CurrentEncoding);
Console.ReadLine();
Console.WriteLine();
}
Các mã sau đây là mã Powershell của tôi để quy nếu một số cpp hoặc h hoặc ml tập tin được encodeding với tiêu chuẩn ISO-8859-1 (Latin-1) hoặc UTF-8 không có BOM, nếu không thì giả sử nó là GB18030. Tôi là một người Trung Quốc làm việc tại Pháp và MSVC tiết kiệm như Latin-1 trên máy tính Pháp và tiết kiệm như GB trên máy tính Trung Quốc, điều này giúp tôi tránh được vấn đề khi trao đổi tập tin nguồn giữa hệ thống và đồng nghiệp của tôi.
Cách đơn giản, nếu tất cả ký tự nằm giữa x00-x7E, ASCII, UTF-8 và Latin-1 đều giống nhau, nhưng nếu tôi đọc tệp không phải ASCII bằng UTF-8, chúng tôi sẽ tìm ký tự hiển thị, vì vậy hãy thử đọc bằng Latin-1.Trong tiếng Latin-1, giữa \ x7F và \ xAF trống, trong khi GB sử dụng đầy đủ giữa x00-xFF vì vậy nếu tôi có bất kỳ giữa hai, nó không phải là Latin-1
Mã được viết bằng PowerShell nhưng sử dụng. để dễ dàng dịch sang C# hoặc F #
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
foreach($i in Get-ChildItem .\ -Recurse -include *.cpp,*.h, *.ml) {
$openUTF = New-Object System.IO.StreamReader -ArgumentList ($i, [Text.Encoding]::UTF8)
$contentUTF = $openUTF.ReadToEnd()
[regex]$regex = '�'
$c=$regex.Matches($contentUTF).count
$openUTF.Close()
if ($c -ne 0) {
$openLatin1 = New-Object System.IO.StreamReader -ArgumentList ($i, [Text.Encoding]::GetEncoding('ISO-8859-1'))
$contentLatin1 = $openLatin1.ReadToEnd()
$openLatin1.Close()
[regex]$regex = '[\x7F-\xAF]'
$c=$regex.Matches($contentLatin1).count
if ($c -eq 0) {
[System.IO.File]::WriteAllLines($i, $contentLatin1, $Utf8NoBomEncoding)
$i.FullName
}
else {
$openGB = New-Object System.IO.StreamReader -ArgumentList ($i, [Text.Encoding]::GetEncoding('GB18030'))
$contentGB = $openGB.ReadToEnd()
$openGB.Close()
[System.IO.File]::WriteAllLines($i, $contentGB, $Utf8NoBomEncoding)
$i.FullName
}
}
}
Write-Host -NoNewLine 'Press any key to continue...';
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
Kiểm tra điều này.
Đây là một cổng của Mozilla phổ Charset Detector và bạn có thể sử dụng nó như thế này ...
public static void Main(String[] args)
{
string filename = args[0];
using (FileStream fs = File.OpenRead(filename)) {
Ude.CharsetDetector cdet = new Ude.CharsetDetector();
cdet.Feed(fs);
cdet.DataEnd();
if (cdet.Charset != null) {
Console.WriteLine("Charset: {0}, confidence: {1}",
cdet.Charset, cdet.Confidence);
} else {
Console.WriteLine("Detection failed.");
}
}
}
Bạn nên biết rằng UDE là GPL – lindexi
Ok nếu bạn lo lắng về giấy phép thì bạn có thể sử dụng giấy phép này. Được cấp phép là MIT và bạn có thể sử dụng nó cho cả phần mềm nguồn mở và phần mềm nguồn đóng. https://www.nuget.org/packages/SimpleHelpers.FileEncoding/ –
Thx, có vẻ như nó có thể hiệu quả với tôi. – lindexi
thể trùng lặp của [Java: Làm thế nào để xác định mã hóa charset đúng một dòng ] (http://stackoverflow.com/questions/499010/java-how-to-determine-the-correct-charset-encoding-of-a-stream) – Oded
Mã hóa nào? UTF-8 so với UTF-16, lớn so với ít người dùng cuối? Hay bạn đang đề cập đến các mã MSDos cũ, chẳng hạn như shift-JIS hoặc Cyrillic, vv? – dthorpe
Một bản sao có thể khác: http://stackoverflow.com/questions/436220/python-is-there-a-way-to-determine-the-encoding-of-text-file – Oded