0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Swift テキストファイル入力 標準入力 共通コード

Last updated at Posted at 2025-06-09

はじめに

ファイルパス名が指定されたら、指定されたファイルからテキストを入力、
ファイルパス名が省略されたら、標準入力からテキストを入力する。

このように動作する テキスト入力関数 を作成しました。

テキストファイル入力 標準入力 共通関数

func readTextFile(filepath: String?) throws -> [String] {
    var lines = [String]()
    if let filepath {
        let contents = try String(contentsOfFile: filepath, encoding: .utf8)
        contents.enumerateLines { line, _ in lines.append(line) }
    } else {
        while let input = readLine() {
            lines.append(input)
        }
    }
    return lines
}

String(contentsOfFile:encoding:)が一括入力のため、標準入力もEOFまで先に入力します。このため、巨大ファイルサイズには不向きです。

使い方

上記関数を呼び出す例

test.swift
import Foundation
let test: () = {
    let arguments = CommandLine.arguments
    let filename: String? = arguments.count > 1 ? arguments[1] : nil
    do {
        let text = try readTextFile(filepath: filename)
        print(text)
    } catch {
        print(error.localizedDescription)
    }
}()
実行結果
% swiftc test.swift 

% ./test a.txt # filepath
["123", "ABC"]

% ./test <a.txt # stdin
["123", "ABC"]

% cat a.txt
123
ABC
実行結果(エラー)
% cat b.txt
cat: b.txt: No such file or directory

% ./test b.txt #filepath 
The file “b.txt” couldn’t be opened because there is no such file.

% ./test <b.txt #stdin
zsh: no such file or directory: b.txt

イテレータ版

ついでに、イテレータ版も作成しました。

イテレータ版
struct readTextFile: Sequence, IteratorProtocol, Sendable  {
    @usableFromInline
    internal var array: [String]? = nil
    @usableFromInline
    internal var index = 0
    init(filepath: String?) throws {
        if let filepath {
            let contents = try String(contentsOfFile: filepath, encoding: .utf8)
            var array = [String]()
            contents.enumerateLines { line, _ in array.append(line) }
            self.array = array
        } else {
            array = []
            while let input = readLine() {
                array!.append(input)
            }
        }
    }
    @inlinable
    public mutating func next() -> String? {
        if let array {
            if index < array.count {
                defer { index += 1 }
                return array[index]
            }
        }
        return nil
    }
}

使い方

上記イテレータ版を呼び出す例

test.swift
import Foundation
let test: () = {
    let arguments = CommandLine.arguments
    let filename: String? = arguments.count > 1 ? arguments[1] : nil
    do {
        for line in try readTextFile(filepath: filename) {
            print(line)
        }
    } catch {
        print(error.localizedDescription)
    }
}()
実行結果
% swiftc test.swift 

% ./test a.txt # filepath
123
ABC

% ./test <a.txt # stdin
123
ABC

追伸

stdinを再割り当てする方法がもっと簡単でした。次の記事にします。



以上

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?