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

时间:2015-08-03 02:39:40

标签: ios arrays swift text nsstring

刚开始学习Swift,我已经从文本文件中读取了代码,应用程序显示了整个文本文件的内容。如何逐行显示并多次调用该行?

TextFile.txt包含以下内容。

  1. 香蕉
  2. 苹果
  3. 草莓
  4. 蓝莓
  5. 黑醋栗
  6. 以下是目前的......

     twogrp <- c(rnorm(10)+4,rnorm(10)+20)
     gap.barplot(twogrp, gap = c(8,16), ytics = c(3,6,17,20))
    

    如果还有其他方式,请告诉我。非常感谢

6 个答案:

答案 0 :(得分:74)

Swift 3.0

if let path = Bundle.main.path(forResource: "TextFile", ofType: "txt") {
    do {
        let data = try String(contentsOfFile: path, encoding: .utf8)
        let myStrings = data.components(separatedBy: .newlines)
        TextView.text = myStrings.joined(separator: ", ")
    } catch {
        print(error)
    }
}

变量myStrings应该是数据的每一行。

使用的代码来自: Reading file line by line in iOS SDK用Obj-C编写并使用NSString

检查以前版本的Swift的编辑历史记录。

答案 1 :(得分:10)

Swift 5.2

下面的解决方案显示了如何一次读取一行。这与将全部内容读入内存完全不同。如果要读取的文件较大,则逐行读取的缩放效果很好。对于大文件,将整个文件放入内存无法很好地扩展。

下面的示例使用while循环,当没有更多行时退出,但是您可以根据需要选择其他数量的行进行读取。

代码工作如下:

  1. 创建一个URL,该URL指示文件的位置
  2. 确保文件存在
  3. 打开文件进行阅读
  4. 设置一些初始变量以供阅读
  5. 使用getLine()
  6. 阅读每一行
  7. 完成后关闭文件

如果愿意,可以使代码不太冗长;我已经添加了注释,以解释变量的用途。

Swift 5.2

import Cocoa

// get URL to the the documents directory in the sandbox
let home = FileManager.default.homeDirectoryForCurrentUser

// add a filename
let fileUrl = home
    .appendingPathComponent("Documents")
    .appendingPathComponent("my_file")
    .appendingPathExtension("txt")


// make sure the file exists
guard FileManager.default.fileExists(atPath: fileUrl.path) else {
    preconditionFailure("file expected at \(fileUrl.absoluteString) is missing")
}

// open the file for reading
// note: user should be prompted the first time to allow reading from this location
guard let filePointer:UnsafeMutablePointer<FILE> = fopen(fileUrl.path,"r") else {
    preconditionFailure("Could not open file at \(fileUrl.absoluteString)")
}

// a pointer to a null-terminated, UTF-8 encoded sequence of bytes
var lineByteArrayPointer: UnsafeMutablePointer<CChar>? = nil

// the smallest multiple of 16 that will fit the byte array for this line
var lineCap: Int = 0

// initial iteration
var bytesRead = getline(&lineByteArrayPointer, &lineCap, filePointer)

defer {
    // remember to close the file when done
    fclose(filePointer)
}

while (bytesRead > 0) {
    
    // note: this translates the sequence of bytes to a string using UTF-8 interpretation
    let lineAsString = String.init(cString:lineByteArrayPointer!)
    
    // do whatever you need to do with this single line of text
    // for debugging, can print it
    print(lineAsString)
    
    // updates number of bytes read, for the next iteration
    bytesRead = getline(&lineByteArrayPointer, &lineCap, filePointer)
}

答案 2 :(得分:5)

Swift 2.0 / Xcode 7.2的更新

$output2 = preg_match_all('/\/>(.*?)\[\/caption\]/u', $post->post_content, $matches2);

另外值得一提的是,此代码读取项目文件夹中的文件(因为使用了pathForResource),而不是例如设备的文档文件夹

答案 3 :(得分:3)

您可能确实希望立即阅读整个文件。我打赌它非常小。

但是你想将结果字符串拆分成一个数组,然后在各种UI元素(例如表格单元格)中分发数组的内容。

一个简单的例子:

    var x: String = "abc\ndef"
    var y = x.componentsSeparatedByString("\n")
    // y is now a [String]: ["abc", "def"]

答案 4 :(得分:1)

在Swift 5.0中可能最简单,最简单的方法如下:

import Foundation

// Determine the file name
let filename = "main.swift"

// Read the contents of the specified file
let contents = try! String(contentsOfFile: filename)

// Split the file into separate lines
let lines = contents.split(separator:"\n")

// Iterate over each line and print the line
for line in lines {
    print("\(line)")
}

贷方转到:https://wiki.codermerlin.com/mediawiki/index.php/Code_Snippet:_Print_a_File_Line-by-Line

答案 5 :(得分:0)

这并不漂亮,但是我相信它可以工作(在Swift 5上)。这使用基础的POSIX getline命令进行迭代和文件读取。

typealias LineState = (
  // pointer to a C string representing a line
  linePtr:UnsafeMutablePointer<CChar>?,
  linecap:Int,
  filePtr:UnsafeMutablePointer<FILE>?
)

/// Returns a sequence which iterates through all lines of the the file at the URL.
///
/// - Parameter url: file URL of a file to read
/// - Returns: a Sequence which lazily iterates through lines of the file
///
/// - warning: the caller of this function **must** iterate through all lines of the file, since aborting iteration midway will leak memory and a file pointer
/// - precondition: the file must be UTF8-encoded (which includes, ASCII-encoded)
func lines(ofFile url:URL) -> UnfoldSequence<String,LineState>
{
  let initialState:LineState = (linePtr:nil, linecap:0, filePtr:fopen(fileURL.path,"r"))
  return sequence(state: initialState, next: { (state) -> String? in
    if getline(&state.linePtr, &state.linecap, state.filePtr) > 0,
      let theLine = state.linePtr  {
      return String.init(cString:theLine)
    }
    else {
      if let actualLine = state.linePtr  { free(actualLine) }
      fclose(state.filePtr)
      return nil
    }
  })
}

以下是您可能会使用它的方式:

for line in lines(ofFile:myFileURL) {
  print(line)
}