2008-11-10 45 views

Trả lời

1

Vâng, điều này phụ thuộc vào định nghĩa của bạn về ASCII. Bạn có thể kiểm tra các giá trị bằng mã ASCII < 128 hoặc cho một số ký tự mà bạn xác định (ví dụ: 'a' - 'z', 'A' - 'Z', '0' - '9' ...) và xử lý tệp dưới dạng nhị phân nếu nó chứa một số ký tự khác.

Bạn cũng có thể kiểm tra các ngắt dòng thông thường (0x10 hoặc 0x13,0x10) để phát hiện tệp văn bản.

8

Nội dung của mỗi tệp là nhị phân. Vì vậy, không biết gì khác, bạn không thể chắc chắn.

ASCII là vấn đề giải thích. Nếu bạn mở một tệp nhị phân trong trình soạn thảo văn bản, bạn sẽ hiểu ý tôi.

Hầu hết các tệp nhị phân chứa một tiêu đề cố định (cho mỗi loại) bạn có thể tìm kiếm hoặc bạn có thể lấy phần mở rộng tệp làm gợi ý. Bạn có thể tìm kiếm các dấu hiệu thứ tự byte nếu bạn mong đợi các tệp được mã hóa UTF, nhưng chúng cũng là tùy chọn.

Trừ khi bạn xác định câu hỏi của mình chặt chẽ hơn, không thể có câu trả lời dứt khoát.

15

Bạn lặp qua nó bằng cách sử dụng vòng lặp bình thường với stream.get() và kiểm tra xem các giá trị byte bạn đọc là <= 127. Một trong nhiều cách để làm điều đó:

int c; 
std::ifstream a("file.txt"); 
while((c = a.get()) != EOF && c <= 127) 
    ; 
if(c == EOF) { 
    /* file is all ASCII */ 
} 

Tuy nhiên, như ai đó đã đề cập, tất cả các tệp đều là tệp nhị phân. Ngoài ra, nó không rõ ràng những gì bạn có nghĩa là "ascii". Nếu bạn có nghĩa là mã ký tự, thì thực sự đây là cách bạn đi. Nhưng nếu bạn chỉ có nghĩa là giá trị chữ và số, bạn sẽ cần một cách khác để đi.

+1

Tôi không nghĩ đó là những gì tác giả dự định. Nhưng * thực tế * đây là câu trả lời đúng. :-) – Tomalak

+0

Đó là câu trả lời đúng cho câu hỏi được hỏi. Tuy nhiên Tomalak bạn đúng trong đó có lẽ đã không nói đúng câu hỏi. –

+1

Tôi biểu thức "ASCII hoặc nhị phân" là một gợi ý rằng anh ta thực sự có nghĩa là "văn bản, trái ngược với nhị phân". – Tomalak

51

Nếu tệp có chứa chỉ byte thập phân 9 – 13, 32 – 126, đó có thể là tệp văn bản ASCII thuần túy. Nếu không, nó không phải. Tuy nhiên, nó vẫn có thể là văn bản trong mã hóa khác.

Nếu trong Ngoài để các byte trên, các tập tin chứa chỉ các byte chữ số thập phân 128 – 255, nó có thể là một tập tin văn bản trong một bảng mã ASCII dựa trên 8-bit hoặc chiều dài thay đổi như ISO- 8859-1, UTF-8 hoặc ASCII + Big5. Nếu không, đối với một số mục đích bạn có thể dừng lại ở đây và coi tập tin là nhị phân. Tuy nhiên, nó vẫn có thể là văn bản trong mã hóa 16 hoặc 32 bit.

Nếu một tập tin không đáp ứng được những hạn chế trên, kiểm tra đầu tiên 2 – 4 byte của tập tin cho một byte-order mark:

  • Nếu hai byte đầu tiên được hex FE FF, các tập tin là tạm UTF-16 BE.
  • Nếu hai byte đầu tiên được hex FF FE, và hai byte sau là không hex 00 00, các tập tin là tạm UTF-16 LE.
  • Nếu bốn byte đầu tiên là hex 00 00 FE FF, tệp là dự kiến ​​ UTF-32 BE.
  • Nếu bốn byte đầu tiên là hex FF FE 00 00, tệp là dự kiến ​​ UTF-32 LE.

Nếu, thông qua các kiểm tra trên, bạn đã xác định mã hóa dự kiến, sau đó chỉ kiểm tra mã hóa tương ứng, để đảm bảo tệp không phải là tệp nhị phân xảy ra khớp với dấu thứ tự byte.

Nếu bạn chưa xác định một mã hóa dự kiến, tập tin vẫn có thể là một tập tin văn bản trong một trong những mã hóa, vì dấu byte đặt hàng là không bắt buộc, vì vậy kiểm tra đối với tất cả các bảng mã trong danh sách sau:

  • Nếu tệp chứa chỉ từ hai byte lớn nhất có giá trị thập phân 9 – 13, 32 – 126 và 128 trở lên, tệp có thể là UTF-16 BE.
  • Nếu tệp chứa chỉ từ hai byte nhỏ nhất có giá trị thập phân 9 – 13, 32 – 126 và 128 trở lên, tệp có thể là UTF-16 LE.
  • Nếu tệp chứa chỉ từ bốn byte lớn cấp có giá trị thập phân 9 – 13, 32 – 126 và 128 hoặc cao hơn, tệp có thể là UTF-32 BE.
  • Nếu tệp có chứa chỉ từ bốn byte nhỏ gọn có giá trị thập phân 9 – 13, 32 – 126 và 128 trở lên, tệp có thể là UTF-32 LE.

Nếu sau tất cả các kiểm tra này, bạn vẫn chưa xác định được mã hóa, tệp không phải là tệp văn bản trong bất kỳ mã ASCII nào mà tôi biết, vì vậy hầu hết các mục đích bạn có thể xem xét là nhị phân (nó có thể vẫn là một tệp văn bản trong một mã hóa không phải ASCII như EBCDIC, nhưng tôi nghi ngờ điều đó nằm ngoài phạm vi quan tâm của bạn).

+1

Điều này chỉ hoạt động nếu văn bản là ASCII. Nếu UTF16 hoặc UTF32, thì nó có thể chứa các byte có giá trị 0-8, 14-31 và 127. Câu trả lời của bạn do đó gây nhầm lẫn. –

+1

@David Arno, Đúng vậy, nhưng câu hỏi thực sự là về ASCII hay không. – quinmars

+0

@quinmars, tôi thu hút sự chú ý của bạn đến dòng đầu tiên của câu trả lời này "Tôi giả sử bạn thực sự muốn phát hiện xem tệp có phải là văn bản (trong bất kỳ mã hóa nào), không chỉ ASCII". Cho rằng, dòng thứ hai là đồng bằng sai. Vì vậy, câu trả lời là nhầm lẫn và gây hiểu nhầm. –

10

Hãy xem cách hoạt động của file command; nó có ba chiến lược để xác định loại của một tập tin:

  • hệ thống tập tin kiểm tra
  • magic number kiểm tra
  • và ngôn ngữ kiểm tra

Tùy thuộc vào nền tảng của bạn, và các tập tin có thể bạn quan tâm trong, bạn có thể nhìn vào việc thực hiện nó, hoặc thậm chí gọi nó.

11

Trình chỉnh sửa văn bản của tôi quyết định về sự hiện diện của các byte rỗng. Trong thực tế, hoạt động thực sự tốt: một tệp nhị phân không có byte rỗng là cực kỳ hiếm.

+2

Đây cũng là điều khác biệt của gnu. độ dài được xác định trước vào tệp. (Không muốn lướt qua một tệp 4GB cho các byte rỗng ...) –

+0

Đây cũng là những gì "grep -I" thực hiện. – kervin

1

Để kiểm tra, bạn phải mở tệp dưới dạng nhị phân. Bạn không thể mở tệp dưới dạng văn bản. ASCII là một tập con nhị phân. Sau đó, bạn phải kiểm tra các giá trị byte. ASCII có giá trị byte 0-127, nhưng 0-31 là các ký tự điều khiển. TAB, CR và LF là các ký tự điều khiển chung duy nhất. Bạn không thể sử dụng 'A' và 'Z'; không có sự bảo đảm nào trong ASCII (!). Nếu bạn cần chúng, bạn sẽ phải xác định.

const unsigned char ASCII_A = 0x41; // NOT 'A' 
const unsigned char ASCII_Z = ASCII_A + 25; 
7

Nếu câu hỏi thực sự là cách phát hiện ASCII, thì câu trả lời của câu trả lời là phát hiện. Tuy nhiên nếu san sau khi biết cách xác định xem tệp có chứa văn bản hay không thì vấn đề trở nên phức tạp hơn. ASCII chỉ là một - ngày càng không phổ biến - cách thể hiện văn bản. Hệ thống Unicode - UTF16, UTF32 và UTF8 đã trở nên phổ biến. Về lý thuyết, chúng có thể dễ dàng được kiểm tra bằng cách kiểm tra xem hai byte đầu tiên có phải là dấu thứ tự byte unicocde (BOM) 0xFEFF (hay 0xFFFE nếu thứ tự byte bị đảo ngược). Tuy nhiên, khi hai byte này tạo ra nhiều định dạng tệp cho các hệ thống Linux, chúng không thể được đảm bảo ở đó. Hơn nữa, một tệp nhị phân có thể bắt đầu bằng 0xFEFF.

Tìm kiếm 0x00 (hoặc các ký tự điều khiển khác) sẽ không giúp ích nếu tệp là unicode. Nếu tệp UFT16 nói và tệp chứa văn bản tiếng Anh thì mọi ký tự khác sẽ là 0x00.

Nếu bạn biết ngôn ngữ mà tệp văn bản sẽ được viết, thì có thể phân tích các byte và xác định thống kê xem nó có chứa văn bản hay không. Ví dụ, chữ cái phổ biến nhất trong tiếng Anh là E tiếp theo là T. Vì vậy, nếu tập tin chứa nhiều hơn E và T hơn của Z và X, nó có khả năng văn bản. Tất nhiên nó sẽ là cần thiết để kiểm tra điều này như ASCII và các unicodes khác nhau để đảm bảo.

Nếu tệp không được viết bằng tiếng Anh - hoặc bạn muốn hỗ trợ nhiều ngôn ngữ - thì chỉ còn hai tùy chọn là xem phần mở rộng tệp trên Windows và kiểm tra bốn byte đầu tiên dựa vào cơ sở dữ liệu tập tin "mã để xác định loại tập tin và do đó cho dù nó có chứa văn bản hay không.

1

Câu hỏi này thực sự không có câu trả lời đúng hay sai cho nó, chỉ là các giải pháp phức tạp sẽ không hoạt động đối với tất cả các tệp văn bản có thể.

Đây là liên kết The Old New Thing Article về cách notepad phát hiện loại tệp ascii. Nó không hoàn hảo, nhưng thật thú vị khi thấy Microsoft xử lý nó như thế nào.

Các vấn đề liên quan