Ich muss Daten in/aus einer Textdatei lesen und schreiben, aber ich konnte nicht herausfinden, wie.
Ich habe diesen Beispielcode im iBook von Swift gefunden, weiß aber noch nicht, wie ich Daten schreiben oder lesen soll.
import Cocoa
class DataImporter
{
/*
DataImporter is a class to import data from an external file.
The class is assumed to take a non-trivial amount of time to initialize.
*/
var fileName = "data.txt"
// the DataImporter class would provide data importing functionality here
}
class DataManager
{
@lazy var importer = DataImporter()
var data = String[]()
// the DataManager class would provide data management functionality here
}
let manager = DataManager()
manager.data += "Some data"
manager.data += "Some more data"
// the DataImporter instance for the importer property has not yet been created”
println(manager.importer.fileName)
// the DataImporter instance for the importer property has now been created
// prints "data.txt”
var str = "Hello World in Swift Language."
Zum Lesen und Schreiben sollten Sie einen Ort verwenden, der beschreibbar ist, z. B. das Dokumentenverzeichnis. Der folgende Code zeigt, wie eine einfache Zeichenfolge gelesen und geschrieben wird. Sie können es auf einem Spielplatz testen.
Swift 3.x und Swift 4.0
let file = "file.txt" //this is the file. we will write to and read from it
let text = "some text" //just a text
if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let fileURL = dir.appendingPathComponent(file)
//writing
do {
try text.write(to: fileURL, atomically: false, encoding: .utf8)
}
catch {/* error handling here */}
//reading
do {
let text2 = try String(contentsOf: fileURL, encoding: .utf8)
}
catch {/* error handling here */}
}
Swift 2.2
let file = "file.txt" //this is the file. we will write to and read from it
let text = "some text" //just a text
if let dir = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first {
let path = NSURL(fileURLWithPath: dir).URLByAppendingPathComponent(file)
//writing
do {
try text.writeToURL(path, atomically: false, encoding: NSUTF8StringEncoding)
}
catch {/* error handling here */}
//reading
do {
let text2 = try NSString(contentsOfURL: path, encoding: NSUTF8StringEncoding)
}
catch {/* error handling here */}
}
Swift 1.x
let file = "file.txt"
if let dirs : [String] = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String] {
let dir = dirs[0] //documents directory
let path = dir.stringByAppendingPathComponent(file);
let text = "some text"
//writing
text.writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding, error: nil);
//reading
let text2 = String(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil)
}
Wenn Sie Ihre Textdatei data.txt
in Ihr Xcode-Projekt verschoben haben (Drag'n'Drop verwenden und "Dateien kopieren, falls erforderlich") können Sie wie in Objective-C Folgendes tun:
let bundle = NSBundle.mainBundle()
let path = bundle.pathForResource("data", ofType: "txt")
let content = NSString.stringWithContentsOfFile(path) as String
println(content) // prints the content of data.txt
Update:
Zum Lesen einer Datei aus Bundle (iOS) können Sie Folgendes verwenden:
let path = NSBundle.mainBundle().pathForResource("FileName", ofType: "txt")
var text = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)!
println(text)
Update für Swift 3:
let path = Bundle.main.path(forResource: "data", ofType: "txt") // file path for file "data.txt"
var text = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)!
Xcode 8.x • Swift 3.x oder höher
do {
// get the documents folder url
if let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
// create the destination url for the text file to be saved
let fileURL = documentDirectory.appendingPathComponent("file.txt")
// define the string/text to be saved
let text = "Hello World !!!"
// writing to disk
// Note: if you set atomically to true it will overwrite the file if it exists without a warning
try text.write(to: fileURL, atomically: false, encoding: .utf8)
print("saving was successful")
// any posterior code goes here
// reading from disk
let savedText = try String(contentsOf: fileURL)
print("savedText:", savedText) // "Hello World !!!\n"
}
} catch {
print("error:", error)
}
Neue einfachere und empfohlene Methode: Apple empfiehlt die Verwendung einer URL zum Filehandling, und die oben genannten Lösungen scheinen veraltet zu sein (siehe Kommentare unten). .__ Die folgende einfache Methode ist das Lesen und Schreiben mit URLs (vergessen Sie nicht, mögliche URL-Fehler zu behandeln):
Swift 4.0 und 3.1
import Foundation // Needed for those pasting into Playground
let fileName = "Test"
let dir = try? FileManager.default.url(for: .documentDirectory,
in: .userDomainMask, appropriateFor: nil, create: true)
// If the directory was found, we write a file to it and read it back
if let fileURL = dir?.appendingPathComponent(fileName).appendingPathExtension("txt") {
// Write to the file named Test
let outString = "Write this text to the file"
do {
try outString.write(to: fileURL, atomically: true, encoding: .utf8)
} catch {
print("Failed writing to URL: \(fileURL), Error: " + error.localizedDescription)
}
// Then reading it back from the file
var inString = ""
do {
inString = try String(contentsOf: fileURL)
} catch {
print("Failed reading from URL: \(fileURL), Error: " + error.localizedDescription)
}
print("Read from the file: \(inString)")
}
Xcode 8, Swift 3-Wege, um Dateien aus dem App-Paket zu lesen:
if let path = Bundle.main.path(forResource: filename, ofType: nil) {
do {
let text = try String(contentsOfFile: path, encoding: String.Encoding.utf8)
print(text)
} catch {
printError("Failed to read text from \(filename)")
}
} else {
printError("Failed to load file from app bundle \(filename)")
}
Hier ist eine praktische Erweiterung zum Kopieren und Einfügen
public extension String {
func contentsOrBlank()->String {
if let path = Bundle.main.path(forResource:self , ofType: nil) {
do {
let text = try String(contentsOfFile:path, encoding: String.Encoding.utf8)
return text
} catch { print("Failed to read text from bundle file \(self)") }
} else { print("Failed to load file from bundle \(self)") }
return ""
}
}
Zum Beispiel
let t = "yourFile.txt".contentsOrBlank()
Sie möchten fast immer ein Zeilenarray:
let r:[String] = "yourFile.txt"
.contentsOrBlank()
.characters
.split(separator: "\n", omittingEmptySubsequences:ignore)
.map(String.init)
Ich möchte Ihnen nur den ersten Teil zeigen, das heißt lesen . So einfach können Sie lesen:
Swift 3:
let s = try String(contentsOfFile: Bundle.main.path(forResource: "myFile", ofType: "txt")!)
Swift 2:
let s = try! String(contentsOfFile: NSBundle.mainBundle().pathForResource("myFile", ofType: "txt")!)
Einfachste Möglichkeit, eine Datei in Swift> 4.0 zu lesen
let path = Bundle.main.path(forResource: "data", ofType: "txt") // file path for file "data.txt"
do {
var text = try String(contentsOfFile: path!)
}
catch(_){print("error")}
}
Die derzeit akzeptierte Antwort von Adam hatte einige Fehler für mich, aber hier habe ich seine Antwort überarbeitet und diese Arbeit für mich gemacht.
let file = "file.txt"
let dirs: [String]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
if (dirs != nil) {
let directories:[String] = dirs!
let dirs = directories[0]; //documents directory
let path = dirs.stringByAppendingPathComponent(file);
let text = "some text"
//writing
text.writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding, error: nil);
//reading
var error:NSError?
//reading
let text2 = String(contentsOfFile: path, encoding:NSUTF8StringEncoding, error: &error)
if let theError = error {
print("\(theError.localizedDescription)")
}
}
Dieses Tool kann nützlich sein, um Dateien nicht nur in Swift zu lesen, sondern auch Ihre Eingabe zu analysieren: https://github.com/shoumikhin/StreamScanner
Geben Sie einfach den Dateipfad und die Datenbegrenzer folgendermaßen an:
import StreamScanner
if let input = NSFileHandle(forReadingAtPath: "/file/path")
{
let scanner = StreamScanner(source: input, delimiters: NSCharacterSet(charactersInString: ":\n")) //separate data by colons and newlines
while let field: String = scanner.read()
{
//use field
}
}
Hoffe das hilft.
Letzter Swift3-Code
Sie können Daten aus einer Textdatei lesen. Verwenden Sie dazu den folgenden Code .__
{
"NumberOfSlices": "8",
"NrScenes": "5",
"Scenes": [{
"dataType": "label1",
"image":"http://is3.mzstatic.com/image/thumb/Purple19/v4/6e/81/31/6e8131cf-2092-3cd3-534c-28e129897ca9/mzl.syvaewyp.png/53x53bb-85.png",
"value": "Hello",
"color": "(UIColor.red)"
}, {
"dataType": "label2",
"image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/6c/4c/c1/6c4cc1bc-8f94-7b13-f3aa-84c41443caf3/mzl.hcqvmrix.png/53x53bb-85.png",
"value": "Hi There",
"color": "(UIColor.blue)"
}, {
"dataType": "label3",
"image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/6c/4c/c1/6c4cc1bc-8f94-7b13-f3aa-84c41443caf3/mzl.hcqvmrix.png/53x53bb-85.png",
"value": "hi how r u ",
"color": "(UIColor.green)"
}, {
"dataType": "label4",
"image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/6c/4c/c1/6c4cc1bc-8f94-7b13-f3aa-84c41443caf3/mzl.hcqvmrix.png/53x53bb-85.png",
"value": "what are u doing ",
"color": "(UIColor.purple)"
}, {
"dataType": "label5",
"image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/6c/4c/c1/6c4cc1bc-8f94-7b13-f3aa-84c41443caf3/mzl.hcqvmrix.png/53x53bb-85.png",
"value": "how many times ",
"color": "(UIColor.white)"
}, {
"dataType": "label6",
"image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/5a/f3/06/5af306b0-7cac-1808-f440-bab7a0d18ec0/mzl.towjvmpm.png/53x53bb-85.png",
"value": "hi how r u ",
"color": "(UIColor.blue)"
}, {
"dataType": "label7",
"image":"http://is5.mzstatic.com/image/thumb/Purple71/v4/a8/dc/eb/a8dceb29-6daf-ca0f-d037-df9f34cdc476/mzl.ukhhsxik.png/53x53bb-85.png",
"value": "hi how r u ",
"color": "(UIColor.gry)"
}, {
"dataType": "label8",
"image":"http://is2.mzstatic.com/image/thumb/Purple71/v4/15/23/e0/1523e03c-fff2-291e-80a7-73f35d45c7e5/mzl.zejcvahm.png/53x53bb-85.png",
"value": "hi how r u ",
"color": "(UIColor.brown)"
}]
}
Mit diesem Code können Sie Daten aus einer Text-Json-Datei in Swift3 abrufen
let filePath = Bundle.main.path(forResource: "nameoftheyourjsonTextfile", ofType: "json")
let contentData = FileManager.default.contents(atPath: filePath!)
let content = NSString(data: contentData!, encoding: String.Encoding.utf8.rawValue) as? String
print(content)
let json = try! JSONSerialization.jsonObject(with: contentData!) as! NSDictionary
print(json)
let app = json.object(forKey: "Scenes") as! NSArray!
let _ : NSDictionary
for dict in app! {
let colorNam = (dict as AnyObject).object(forKey: "color") as! String
print("colors are \(colorNam)")
// let colour = UIColor(hexString: colorNam) {
// colorsArray.append(colour.cgColor)
// colorsArray.append(colorNam as! UIColor)
let value = (dict as AnyObject).object(forKey: "value") as! String
print("the values are \(value)")
valuesArray.append(value)
let images = (dict as AnyObject).object(forKey: "image") as! String
let url = URL(string: images as String)
let data = try? Data(contentsOf: url!)
print(data)
let image1 = UIImage(data: data!)! as UIImage
imagesArray.append(image1)
print(image1)
}
Ich musste so umkodieren:
let path = NSBundle.mainBundle().pathForResource("Output_5", ofType: "xml")
let text = try? NSString(contentsOfFile: path! as String, encoding: NSUTF8StringEncoding)
print(text)
Um Verwirrung zu vermeiden und die Benutzerfreundlichkeit zu verbessern, habe ich zwei Funktionen zum Lesen und Schreiben von Zeichenfolgen in Dateien im Dokumentenverzeichnis erstellt. Hier sind die Funktionen:
func writeToDocumentsFile(fileName:String,value:String) {
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! NSString
let path = documentsPath.stringByAppendingPathComponent(fileName)
var error:NSError?
value.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding, error: &error)
}
func readFromDocumentsFile(fileName:String) -> String {
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! NSString
let path = documentsPath.stringByAppendingPathComponent(fileName)
var checkValidation = NSFileManager.defaultManager()
var error:NSError?
var file:String
if checkValidation.fileExistsAtPath(path) {
file = NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil) as! String
} else {
file = "*ERROR* \(fileName) does not exist."
}
return file
}
Hier ist ein Beispiel für ihre Verwendung:
writeToDocumentsFile("MyText.txt","Hello world!")
let value = readFromDocumentsFile("MyText.txt")
println(value) //Would output 'Hello world!'
let otherValue = readFromDocumentsFile("SomeText.txt")
println(otherValue) //Would output '*ERROR* SomeText.txt does not exist.'
Hoffe das hilft!
Xcode-Version: 6.3.2
Im Funktionsbeispiel (lesen | schreiben) scheint DocumentsFromFile (...) mit einigen Wrapper-Funktionen sicherlich sinnvoll zu sein, da alles in OSx und iOS drei oder vier Hauptklassen zu instanziieren scheint und eine Reihe von Eigenschaften, konfiguriert, verknüpft, instanziiert und festgelegt, nur um "Hi" in eine Datei zu schreiben, in 182 Ländern.
Diese Beispiele sind jedoch nicht vollständig genug, um in einem echten Programm verwendet zu werden. Die Schreibfunktion meldet keine Fehler beim Erstellen oder Schreiben in die Datei. Beim Lesen denke ich nicht, dass es eine gute Idee ist, einen Fehler zurückzugeben, dass die Datei nicht als Zeichenfolge vorhanden ist, die die gelesenen Daten enthalten soll. Sie möchten wissen, dass es fehlgeschlagen ist und warum durch einen Benachrichtigungsmechanismus wie eine Ausnahme. Dann können Sie Code schreiben, der das Problem ausgibt und dem Benutzer ermöglicht, das Problem zu beheben, oder das Programm wird "richtig" an diesem Punkt unterbrochen.
Sie möchten nicht einfach eine Zeichenfolge mit der Fehlermeldung "Fehlerdatei ist nicht vorhanden" zurückgeben. Sie müssten dann jedes Mal nach dem Fehler in der Zeichenfolge suchen, indem Sie die Funktion aufrufen und dort behandeln. Sie konnten möglicherweise auch nicht wirklich feststellen, ob die Fehlerzeichenfolge tatsächlich aus einer tatsächlichen Datei gelesen wurde oder ob sie aus Ihrem Code erstellt wurde.
Sie können das Lesen in Swift 2.2 und Xcode 7.3 nicht einmal so aufrufen, da NSString (contentsOfFile ...) eine Ausnahme auslöst. Es ist ein Fehler bei der Kompilierung, wenn Sie keinen Code zum Abfangen haben und etwas damit tun, z. B. den Ausdruck in stdout oder besser ein Fehler-Popup-Fenster oder stderr. Ich habe gehört, dass Apple sich von Try Catch und Exceptions entfernt, aber es wird ein langer Schritt sein und es ist nicht möglich, Code ohne das zu schreiben. Ich weiß nicht, woher das & error-Argument stammt, vielleicht eine ältere Version, aber NSString.writeTo [File | URL] hat derzeit kein NSError-Argument. Sie sind wie folgt in NSString.h definiert:
public func writeToURL(url: NSURL, atomically useAuxiliaryFile: Bool, encoding enc: UInt) throws
public func writeToFile(path: String, atomically useAuxiliaryFile: Bool, encoding enc: UInt) throws
public convenience init(contentsOfURL url: NSURL, encoding enc: UInt) throws
public convenience init(contentsOfFile path: String, encoding enc: UInt) throws
Die nicht vorhandene Datei ist nur eines von mehreren möglichen Problemen, die Ihr Programm beim Lesen einer Datei haben kann, z. B. ein Berechtigungsproblem, die Dateigröße oder zahlreiche andere Probleme, für die Sie nicht einmal versuchen möchten, einen Handler zu codieren jeder von Ihnen. Am besten nehmen Sie einfach an, dass alles korrekt ist und fängt und druckt oder behandelt, eine Ausnahme, wenn etwas schief geht. Außerdem haben Sie an diesem Punkt sowieso keine Wahl.
Hier sind meine Überarbeitungen:
func writeToDocumentsFile(fileName:String,value:String) {
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString!
let path = documentsPath.stringByAppendingPathComponent(fileName)
do {
try value.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding)
} catch let error as NSError {
print("ERROR : writing to file \(path) : \(error.localizedDescription)")
}
}
func readFromDocumentsFile(fileName:String) -> String {
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
let path = documentsPath.stringByAppendingPathComponent(fileName)
var readText : String = ""
do {
try readText = NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) as String
}
catch let error as NSError {
print("ERROR : reading from file \(fileName) : \(error.localizedDescription)")
}
return readText
}
Für meine txt-Datei funktioniert das so:
let myFileURL = NSBundle.mainBundle().URLForResource("listacomuni", withExtension: "txt")!
let myText = try! String(contentsOfURL: myFileURL, encoding: NSISOLatin1StringEncoding)
print(String(myText))
schreibe in ViewDidLoad
var error: NSError?
var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
var documentsDirectory = paths.first as String
var dataPath = documentsDirectory.stringByAppendingPathComponent("MyFolder")
if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) {
NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil, error: &error)
} else {
println("not creted or exist")
}
func listDocumentDirectoryfiles() -> [String] {
if let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as? String {
let myFilePath = documentDirectory.stringByAppendingPathComponent("MyFolder")
return NSFileManager.defaultManager().contentsOfDirectoryAtPath(myFilePath, error: nil) as [String]
}
return []
}
Dies funktioniert mit Swift 3.1.1 unter Linux:
import Foundation
let s = try! String(contentsOfFile: "yo", encoding: .utf8)
func writeToDocumentsFile(fileName:String,value:String) {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
let path = documentsPath.appendingPathComponent(fileName)
do{
try value.write(toFile: path, atomically: true, encoding: String.Encoding.utf8)
}catch{
}
}
func readFromDocumentsFile(fileName:String) -> String {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
let path = documentsPath.appendingPathComponent(fileName)
let checkValidation = FileManager.default
var file:String
if checkValidation.fileExists(atPath: path) {
do{
try file = NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue) as String
}catch{
file = ""
}
} else {
file = ""
}
return file
}
Frühere Lösungen beantworten die Frage, aber in meinem Fall war es ein Problem, alten Inhalt der Datei während des Schreibvorgangs zu löschen.
Also habe ich einen Code erstellt, der in das Dokumentverzeichnis geschrieben wurde, ohne dass der vorherige Inhalt gelöscht wurde. Sie benötigen wahrscheinlich eine bessere Fehlerbehandlung, aber ich glaube, es ist ein guter Ausgangspunkt. Swift 4 . Verwendung:
let filename = "test.txt"
createOrOverwriteEmptyFileInDocuments(filename: filename)
if let handle = getHandleForFileInDocuments(filename: filename) {
writeString(string: "aaa", fileHandle: handle)
writeString(string: "bbb", fileHandle: handle)
writeString(string: "\n", fileHandle: handle)
writeString(string: "ccc", fileHandle: handle)
}
Hilfsmethoden:
func createOrOverwriteEmptyFileInDocuments(filename: String){
guard let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
debugPrint("ERROR IN createOrOverwriteEmptyFileInDocuments")
return
}
let fileURL = dir.appendingPathComponent(filename)
do {
try "".write(to: fileURL, atomically: true, encoding: .utf8)
}
catch {
debugPrint("ERROR WRITING STRING: " + error.localizedDescription)
}
debugPrint("FILE CREATED: " + fileURL.absoluteString)
}
private func writeString(string: String, fileHandle: FileHandle){
let data = string.data(using: String.Encoding.utf8)
guard let dataU = data else {
debugPrint("ERROR WRITING STRING: " + string)
return
}
fileHandle.seekToEndOfFile()
fileHandle.write(dataU)
}
private func getHandleForFileInDocuments(filename: String)->FileHandle?{
guard let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
debugPrint("ERROR OPENING FILE")
return nil
}
let fileURL = dir.appendingPathComponent(filename)
do {
let fileHandle: FileHandle? = try FileHandle(forWritingTo: fileURL)
return fileHandle
}
catch {
debugPrint("ERROR OPENING FILE: " + error.localizedDescription)
return nil
}
}
Xcode 8.3.2 Swift 3.x . Verwendung von NSKeyedArchiver und NSKeyedUnarchiver
Datei aus Dokumenten lesen
let documentsDirectoryPathString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let documentsDirectoryPath = NSURL(string: documentsDirectoryPathString)!
let jsonFilePath = documentsDirectoryPath.appendingPathComponent("Filename.json")
let fileManager = FileManager.default
var isDirectory: ObjCBool = false
if fileManager.fileExists(atPath: (jsonFilePath?.absoluteString)!, isDirectory: &isDirectory) {
let finalDataDict = NSKeyedUnarchiver.unarchiveObject(withFile: (jsonFilePath?.absoluteString)!) as! [String: Any]
}
else{
print("File does not exists")
}
Datei in Dokumente schreiben
NSKeyedArchiver.archiveRootObject(finalDataDict, toFile:(jsonFilePath?.absoluteString)!)