如何使用 Swift 将文本文件逐行加载到数组中?
Posted
技术标签:
【中文标题】如何使用 Swift 将文本文件逐行加载到数组中?【英文标题】:How do I load a text file line by line into an array with Swift? 【发布时间】:2014-06-04 14:26:04 【问题描述】:如何将文本文件逐行加载到带有swift
的array
中?
【问题讨论】:
查看这篇文章以获得关于将文本文件转换为线阵列的选项的精彩讨论。 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。使用StringProtocol
的components(separatedBy:)
方法
Foundation
为String
提供了一个名为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。使用StringProtocol
的enumerateSubstrings(in:options:_:)
方法
Foundation
为String
提供了一个名为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。使用NLTokenizer
的enumerateTokens(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) -> [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 将文本文件逐行加载到数组中?的主要内容,如果未能解决你的问题,请参考以下文章