2016-11-27 51 views
-1

我寫的,它使用的Glibc到文本文件加載到字符串這個銀行代碼,但有時它追加垃圾字符,如\U{7F}字符串的結尾(在同一文件),我不知道爲什麼。 Glibc函數的錯誤檢查都沒有提出任何警告。它只是隨機失敗,即使在同一個文件上使用。爲什麼此文件讀取代碼在文件結尾處給予垃圾?

public typealias Cpath = String 
public typealias Unixpath = String 
public typealias CString = UnsafeMutablePointer<CChar> 

public func unix_path(_ path:Cpath) -> Unixpath 
{ 
    guard path.characters.count > 1 
    else { 
     return path 
    } 
    let path_i0 = path.startIndex 
    let path_i2 = path.index(path_i0, offsetBy: 2) 
    var expanded_path:Unixpath = path 
    if path[path.startIndex..<path_i2] == "~/" { 
     expanded_path = String(cString: getenv("HOME")) + 
         path[path.index(path_i0, offsetBy: 1)..<path.endIndex] 
    } 
    return expanded_path 
} 

public func open_text_file(_ path:Cpath) -> String? 
{ 
    let path = unix_path(path) 

    guard let f:UnsafeMutablePointer<FILE> = fopen(path, "rb") 
    else { 
     print("Error, could not open file '\(path)'") 
     return nil 
    } 
    defer { fclose(f) } 

    let fseek_status = fseeko(f, 0, SEEK_END) 
    guard fseek_status == 0 
    else { 
     print("Error, fseeko() failed with error code \(fseek_status)") 
     return nil 
    } 

    let n = ftello(f) 
    guard 0..<CLong.max ~= n 
    else { 
     print("Error, ftello() returned file size outsize of allowed range") 
     return nil 
    } 
    rewind(f) 

    guard let raw_buffer:UnsafeMutableRawPointer = malloc(n*MemoryLayout<CChar>.size) 
    else { 
     print("Error, could not allocate memory buffer") 
     return nil 
    } 
    defer { free(raw_buffer) } 

    let n_read = fread(raw_buffer, MemoryLayout<CChar>.size, n, f) 
    guard n_read == n 
    else { 
     print("Error, fread() read \(n_read) characters out of \(n)") 
     return nil 
    } 
    let cchar_buffer:CString = raw_buffer.assumingMemoryBound(to: CChar.self) 
    return String(cString: cchar_buffer) 
} 

回答

0

我發現這個問題,我認爲省略的應該都在一個C字符串的結尾定點(\U{00})。沒有它,String(cString:)的構造函數只是抽空,直到它在系統內存中找到一個自然發生的x00字節。下面是正確的表格:

... 

// n + 1 to leave room for sentinel 
let cchar_buffer:CString = CString.allocate(capacity: n + 1) 
defer { cchar_buffer.deallocate(capacity: n + 1) } 

let n_read = fread(cchar_buffer, MemoryLayout<CChar>.size, n, f) 
guard n_read == n 
else { 
    print("Error, fread() read \(n_read) characters out of \(n)") 
    return nil 
} 
cchar_buffer[n] = 0 // cap with sentinel 
return String(cString: cchar_buffer)