2015-04-24 15 views
5

Có thể đọc một ký tự UTF-8 từ tệp không?Lua - đọc một ký tự UTF-8 từ tệp

tệp: đọc (1) trả về ký tự lạ thay vào đó, khi tôi in.

function firstLetter(str) 
    return str:match("[%z\1-\127\194-\244][\128-\191]*") 
end 

Hàm trả về một ký tự UTF-8 từ chuỗi ký tự. Tôi cần phải đọc một ký tự UTF-8 theo cách này, nhưng từ tệp đầu vào (không muốn đọc tệp nhất định vào bộ nhớ - qua tệp: đọc ("* tất cả"))

Câu hỏi tương tự như thế này bài: Extract the first letter of a UTF-8 string with Lua

+1

Một cách khá đơn giản nhưng chắc chắn không phải cách rất phổ biến là thực sự "phân tích cú pháp byte (1..6) và chuyển đổi chúng thành giá trị UTF-32". Sử dụng UTF-32 có thể làm cho công cụ dễ dàng hơn trong một số trường hợp, tùy thuộc vào những gì bạn sẽ làm. – BitTickler

+0

Thực hiện chức năng nào khi đọc một ký tự một cách thủ công? Mặc dù điều đó sẽ kết thúc bạn có đọc thêm một nhân vật sau đó bạn cần thiết vì vậy bạn sẽ cần phải tua lại. –

+0

im sẽ tạo ra hiệu chỉnh kiểu chữ (có thể đọc thêm các ký tự tiếng Séc), vì vậy tôi sẽ đọc tập tin đầu vào, tìm lỗi và sửa nó. Nhưng nó không thể làm việc với (cho Lua nhân vật không rõ). Văn bản gốc: ľúbozvučně řeřicha čučoridka ľaľia Văn bản được đọc bởi Lua (trong Zero Brane Studio): [link] (http://i.imgur.com/PcorbzP.png) khi tôi so sánh chữ cái đầu tiên của cả hai, nó không khớp với – Hrablicky

Trả lời

1
function read_utf8_char(file) 
    local c1 = file:read(1) 
    local ctr, c = -1, math.max(c1:byte(), 128) 
    repeat 
    ctr = ctr + 1 
    c = (c - 128)*2 
    until c < 128 
    return c1..file:read(ctr) 
end 
+2

Đây là câu trả lời chính xác cho câu hỏi nhưng không phải là câu trả lời hay mà không có giải thích. –

+0

@TomBlodget - Bản án của bạn không đúng: như bạn thấy, không ai yêu cầu làm rõ câu trả lời của tôi. Có vẻ như bạn đang đối xử với mọi người như những sinh vật ngu ngốc, nên mọi thứ phải được giải thích chi tiết. Ngược lại, tôi nghĩ mọi người đủ thông minh. Tất nhiên, tôi sẵn sàng giải thích thêm nếu ai đó nói cho tôi biết phần nào của câu trả lời của tôi không rõ ràng cho anh ta. –

+0

@TomBlodget - "Khán giả của bạn thông minh hơn bạn tưởng tượng." (Trích dẫn từ [13 Viết Lời khuyên từ Chuck Palahniuk] (http://litreactor.com/essays/chuck-palahniuk/stocking-stuffers-13-writing-tips-from-chuck-palahniuk), mẹo # 2) –

0

bạn cần phải đọc ký tự để các chuỗi bạn đang so khớp luôn có bốn hoặc nhiều trong số họ (mà sẽ cho phép bạn áp dụng logic từ câu trả lời bạn tham chiếu). Nếu sau khi khớp và xóa ký tự UTF-8 thì độ dài là len, sau đó bạn đọc từ tệp 4-len ký tự.

ZeroBrane Studio thay thế các ký tự UTF-8 không hợp lệ bằng ký tự [SYN] khi được in vào bảng đầu ra (như bạn thấy trong ảnh chụp màn hình). This blogpost mô tả logic đằng sau việc phát hiện các ký tự UTF-8 không hợp lệ (trong Lua) và xử lý của chúng trong ZeroBrane Studio.

0

Trong UTF-8 mã hóa số byte thực hiện cho một nhân vật được xác định bởi các byte đầu tiên của nhân vật đó, theo bảng sau (lấy từ RFC 3629:

Char. number range |  UTF-8 octet sequence 
    (hexadecimal) |    (binary) 
--------------------+--------------------------------------------- 
0000 0000-0000 007F | 0xxxxxxx 
0000 0080-0000 07FF | 110xxxxx 10xxxxxx 
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 

Nếu các bit cao nhất byte đầu tiên là "0", sau đó ký tự chỉ có một byte. Nếu các bit cao nhất là "110" thì ký tự có 2 byte và cứ thế.

Những gì bạn có thể làm là đọc một byte từ tệp và xác định số lượng byte tiếp tục bạn cần đọc cho toàn bộ ký tự UTF-8:

function get_one_utf8_character(file) 

    local c1 = file:read(1) 
    if not c1 then return nil end 

    local ncont 
    if  c1:match("[\000-\127]") then ncont = 0 
    elseif c1:match("[\192-\223]") then ncont = 1 
    elseif c1:match("[\224-\239]") then ncont = 2 
    elseif c1:match("[\240-\247]") then ncont = 3 
    else 
    return nil, "invalid leading byte" 
    end 

    local bytes = { c1 } 
    for i=1,ncont do 
    local ci = file:read(1) 
    if not (ci and ci:match("[\128-\191]")) then 
     return nil, "expected continuation byte" 
    end 
    bytes[#bytes+1] = ci 
    end 

    return table.concat(bytes) 
end 
Các vấn đề liên quan