如何使用 Swift 将文本文件逐行加载到数组中?

Posted

技术标签:

【中文标题】如何使用 Swift 将文本文件逐行加载到数组中?【英文标题】:How do I load a text file line by line into an array with Swift? 【发布时间】:2014-06-04 14:26:04 【问题描述】:

如何将文本文件逐行加载到带有swiftarray 中?

【问题讨论】:

查看这篇文章以获得关于将文本文件转换为线阵列的选项的精彩讨论。 codereview.stackexchange.com/a/100813/79551 【参考方案1】:

类似的东西:

func arrayFromContentsOfFileWithName(fileName: String) -> [String]? 
    guard let path = NSBundle.mainBundle().pathForResource(fileName, ofType: "txt") else 
        return nil
    

    do 
        let content = try String(contentsOfFile:path, encoding: NSUTF8StringEncoding)
        return content.componentsSeparatedByString("\n")
     catch _ as NSError 
        return nil
    

此方法假定相关文件位于您的应用程序包中。

【讨论】:

如果文件位于主包之外怎么办?假设我有一个包含完整路径的NSString 这是我第一次看到guard声明【参考方案2】:

使用 Swift 5,根据您的需要,您可以选择以下 3 种方式之一来解决您的问题。


#1。使用StringProtocolcomponents(separatedBy:)方法

FoundationString 提供了一个名为components(separatedBy:) 的方法,声明如下:

func components(separatedBy separator: CharacterSet) -> [String]

返回一个数组,其中包含字符串中的子字符串,这些子字符串已被给定集合中的字符分割。

下面的代码示例显示了如何使用 components(separatedBy:) 并将其参数设置为 CharacterSet.newlines 以便将文本文件的内容逐行加载到数组中:

import Foundation

let path = Bundle.main.path(forResource: "Lorem Ipsum", ofType: "txt")!
let text = try! String(contentsOfFile: path, encoding: String.Encoding.utf8)
let lines = text.components(separatedBy: CharacterSet.newlines)

print(lines)

作为替代方案,您可以使用overloading of components(separatedBy:),它采用String 类型的参数。下面的代码示例展示了如何使用它:

import Foundation

let path = Bundle.main.path(forResource: "Lorem Ipsum", ofType: "txt")!
let text = try! String(contentsOfFile: path, encoding: String.Encoding.utf8)
let lines = text.components(separatedBy: "\n")

print(lines)

⚠️ 但是,您应该更喜欢 components(separatedBy:) 的重载,它采用 CharacterSet 参数并将其与值 CharacterSet.newlines 一起使用,因为这将管理所有换行符(U+000A ~ U+000D, U+0085 、U+2028 和 U+2029)。


#2。使用StringProtocolenumerateSubstrings(in:options:_:)方法

FoundationString 提供了一个名为enumerateSubstrings(in:options:_:) 的方法。下面的代码示例展示了如何使用 enumerateSubstrings(in:options:_:) 并将 options 参数值设置为 String.EnumerationOptions.byLines 以便将文本文件的内容逐行加载到数组中:

import Foundation

let path = Bundle.main.path(forResource: "Lorem Ipsum", ofType: "txt")!
let text = try! String(contentsOfFile: path, encoding: String.Encoding.utf8)

let range = text.startIndex ..< text.endIndex
var lines = [String]()
text.enumerateSubstrings(in: range, options: String.EnumerationOptions.byLines) 
    (substring, range, enclosingRange, stop) in
    guard let substring = substring else  return 
    lines.append(substring)


print(lines)

#3。使用NLTokenizerenumerateTokens(in:using:)方法

NLTokenizer 有一个名为enumerateTokens(in:using:) 的方法。 enumerateTokens(in:using:) 有以下声明:

@nonobjc func enumerateTokens(in range: Range<String.Index>, using block: (Range<String.Index>, NLTokenizer.Attributes) -> Bool)

枚举字符串的给定范围并为每个标记调用指定的块。

下面的代码示例显示了如何使用enumerateTokens(in:using:) 将文本文件的内容逐行加载到数组中:

import Foundation
import NaturalLanguage

let path = Bundle.main.path(forResource: "Lorem Ipsum", ofType: "txt")!
let text = try! String(contentsOfFile: path, encoding: String.Encoding.utf8)

let tokenizer = NLTokenizer(unit: .paragraph)
tokenizer.setLanguage(.english)
tokenizer.string = text

var lines = [String]()
tokenizer.enumerateTokens(in: text.startIndex ..< text.endIndex)  (range, attributes) -> Bool in
    let line = String(text[range])
    lines.append(line)
    return true

print(lines)

【讨论】:

这是一个很好的答案!【参考方案3】:

基于公认答案的 Swift 3 版本:

func arrayFromContentsOfFileWithName(fileName: String) -> [String]? 
    guard let path = Bundle.main.path(forResource: fileName, ofType: "txt") else 
        return nil
    

    do 
        let content = try String(contentsOfFile:path, encoding: String.Encoding.utf8)
        return content.components(separatedBy: "\n")
     catch 
        return nil
    

【讨论】:

不要吹毛求疵,但签名可能会更好func arrayFromContentsOfFile(with fileName: String) -&gt; [String]?【参考方案4】:

如果你使用的是 Swift 2.0,你应该使用:

let path = NSBundle.mainBundle().pathForResource(fileName, ofType: nil)
if path == nil 
  return nil


var fileContents: String? = nil
do 
  fileContents = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding)
 catch _ as NSError 
  return nil

【讨论】:

你忘了var lineArray = fileContents.componantsSeparedByString("\n")【参考方案5】:

这仅在 Xcode 6.1 beta 1 之前有效。在 6.1 beta 2 中,您必须这样写:

var err: NSError? = NSError()
let s = String(contentsOfFile: fullPath, encoding: NSUTF8StringEncoding, error: &err)

其中fullPath 是包含文件完整路径的字符串,NSUTF8StringEncoding 是 UTF8 编码的预定义常量。

您还可以将NSMacOSRomanStringEncoding 用于 Mac 文件,或将NSISOLatin1StringEncoding 用于 Windows 文件。

s是一个可选的String,你可以看看读取文件是否成功:

if (s != nil)

    return (s!) // Return the string as "normal" string, not as optional string

【讨论】:

这似乎在 Xcode 6 的最终版本中也不再起作用。尝试 let string = String.stringWithContentsOfFile(fullPath, encoding: NSUTF8StringEncoding, error:&error)【参考方案6】:

我给你的简单编码

 let path = NSBundle.mainBundle().pathForResource("FileName", ofType: "txt")
 var text = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)!
 println(text)
 var array = text.componentsSeparatedByString("\n")

【讨论】:

【参考方案7】:

Swift 3.0

if let path = Bundle.main.path(forResource: <#FileName#>, ofType: "txt")

    do
    
        let str = try String(contentsOfFile:path, encoding: String.Encoding.utf8)
        return str.components(separatedBy: "\n")
    
    catch
    

    

else

    return nil

【讨论】:

【参考方案8】:

对我来说工作如下:

let myFileURL = NSBundle.mainBundle().URLForResource("listacomuni", withExtension: "txt")!
let myText = try! String(contentsOfURL: myFileURL, encoding: NSISOLatin1StringEncoding)
print(String(myText))

【讨论】:

【参考方案9】:

如果您想读取数字数据的 csv 文件。 (基于 Cezar 的回答)

func get_csv_data() -> [[Double]] 
    guard let path = NSBundle.mainBundle().pathForResource("filename_without_extension", ofType: "csv") else 
        return []
    
    do 
        let content = try String(contentsOfFile:path, encoding: NSUTF8StringEncoding)
        let line_str_array = content.componentsSeparatedByString("\n")
        return line_str_array.map 
            let field_str_array = $0.componentsSeparatedByString(",")
            return field_str_array.map 
                Double($0)!
            
        
     catch _ as NSError 
        return []
    

【讨论】:

以上是关于如何使用 Swift 将文本文件逐行加载到数组中?的主要内容,如果未能解决你的问题,请参考以下文章

swift2将文本文件的内容加载到变量中

使用数组Swift 5 Xcode iOS替换文本文件中的特定行

在 Swift 中逐行读取文件/URL

在 Swift 中逐行读取文本文件?

在Swift中逐行读取文本文件?

将文本文件逐行读入并行数组C++