如何在 Xcode 项目中将字典数组写入 .txt 文件

Posted

技术标签:

【中文标题】如何在 Xcode 项目中将字典数组写入 .txt 文件【英文标题】:How to write an array of dictionaries to a .txt file in Xcode Project 【发布时间】:2017-06-16 13:18:36 【问题描述】:

我正在从 Firebase 检索数据,然后将接收到的 FIRDataSnapshot 类型的数组转换为 [String:Any] 类型的字典数组。 如何将这个字典数组以有序列表的形式输出到我的 Xcode 项目中的 .txt 文件?

txt文件中打印的输出应该是这样的格式:

预订 1: 电子邮件地址:johnmm@gmail.com 电话号码:94949392 . . 预订 4: 电子邮件地址:chris@gmail.com 电话号码:202583963

在我的问题的底部,您会发现原始数据在 finalDictionary 中的样子

我认为逻辑应该是这样的: 1.循环遍历finalDictionary的元素 2. 取数组的每个元素,给它赋值+换行

let finalDictionary = [String:Any]()

func startObservingDB() 

  dbRef.child(FullData.uid!).observe(.value, with:  (snapshot: FIRDataSnapshot) in

        // an instance of FireBaseData holding all bookings under currentUid
        var newBookingInfo = [FireBaseData]()

//iterate over all children under /FullData.uid! path
   for customer in snapshot.children 

      //the customer node starting with cus...
        let customerObject = customer as! FIRDataSnapshot

       //customer key
          self.customerKey = customerObject.key
             print("this is the Stripe customer that can be charged \(customerObject.key)")

   //now iterate over each booking which is located under customerObject in Firebase
     for booking in customerObject.children 


         // after each iteration through snapshot.children, create an instance of FireBaseData with  'booking' for the current iteration & assign it to bookingItem
            var bookingItem = FireBaseData(snapshot: booking as! FIRDataSnapshot)

        //assign key of the parent to each booking
                bookingItem.Key = self.customerKey

            // append the bookingItem after each iteration to newBookingInfo array
            newBookingInfo.append(bookingItem)

          // end of  for booking in myCustomer
     // end of  for customer in snapshot.children

         //assign newBookingInfo to global variable bookingInfo so it can be used globally within the class
         self.bookingInfo = newBookingInfo

  // sort the array in place so that the most recent date will appear first
 self.bookingInfo.sort(by: (DateAndTimeObject_1,DateAndTimeObject_2) -> Bool in

     DateAndTimeObject_1.TimeStampDateAndTime > DateAndTimeObject_2.TimeStampDateAndTime
  )


  // convert bookingInfo of type FIrebaseData to Array of Dictionaries
   let arrayOfDictionary = self.bookingInfo.flatMap  $0.toAnyObject() as? [String:Any] 

  finalDictionary =  arrayOfDictionary
   print("arrayOfDictionary is \(arrayOfDictionary)")

 //I can write a string to a file in Xcode project using the code snippet 
 //below, but this does not solve my problem, namely to output all elements 
 //of the array as specified above with a break space after each element 
//so that they can be in a human readable format. 

 let fileName = "myBookings"
  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
     if let fileURL = dir?.appendingPathComponent(fileName).appendingPathExtension("txt") 

     // Write to the file
     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)
       





          self.tableView.reloadData()
      , withCancel:  (Error:Any) in
        print("Error firebase \(Error)")
    )
   // end of startObservingDB()



func exportBookings()

 let path = URL(string: "file:///Users/bogdanbarbulescu/Desktop/Test.txt")

        //writing
        do   
            try (finalDictionary).description.write(to: path!, atomically: false, encoding: .utf8)
        
        catch let error  print("The error is \(error.localizedDescription)") 
   

print("arrayOfDictionary is (arrayOfDictionary)") 的输出是:

字典数组是 [["EmailAddress": johnmm@gmail.com, "PhoneNumber": 94949392,“PaymentID”:ch_1AVK6KLCZ34Ur7XGsbROjWhe,“BookingAmount”: 37、“BookingCompleted”:0、“NoteInstructions”:带狗出门 请,“insideCabinets”:true,“BookingNumber”:883924391, “BookingStatusAdmin”:0,“insideFridge”:真,“FrequencyName”:每 2 周,“EntryInstructions”:地毯下的钥匙,“FullName”:James, “SuppliesAmount”:0,“FirebaseUserID”:7b1eRsa9QWhdtA5EwyD2FiPZHSh2, “TimeStampDateAndTime”:1497790800,“邮政编码”:W3 7RZ, “SelectedBathRow”:2,“FrequcyAmount”:22,“laundryWash”:假, “StreetAddress”:11 High St,“CostToRescheduleClient”:0, “BookingStatusClient”:1,“TimeStampBookingSavedInDB”:1497618179, “FlatNumber”:Conely,“SelectedBedRow”:1,“interiorWindows”:0, “CostToCancelClient”:0,“DoormanOption”:隐藏键,“DateAndTime”: 2017 年 6 月 18 日星期日 14:00,“insideOven”:true,“SuppliesName”:我有 清洁用品],

[“电子邮件地址”:johnmm@gmail.com,“电话号码”:07476953923, “PaymentID”:ch_1ATTRHLCZ34Ur7XGL2CGN1I3,“BookingAmount”:63, “BookingCompleted”:0,“NoteInstructions”:否,“insideCabinets”:true, “BookingNumber”:173009560,“BookingStatusAdmin”:1,“insideFridge”: true,“FrequencyName”:每 2 周,“EntryInstructions”:simbasdada, “CostToRescheduleAdmin”:0,“全名”:John Luch,“SuppliesAmount”: 5、“Firebase 用户 ID”:7b1eRsa9QWhdtA5EwyD2FiPZHSh2, “TimeStampDateAndTime”:1497632400,“邮政编码”:IG11 6PP, “SelectedBathRow”:2,“FrequcyAmount”:33,“laundryWash”:真, “StreetAddress”:高街,“CostToRescheduleClient”:0, “BookingStatusClient”:1,“TimeStampBookingSavedInDB”:1497177419, “FlatNumber”:Flat 11,“SelectedBedRow”:2,“interiorWindows”:0, "DoormanOption": Hidden-Key, "DateAndTime": Fri, 16 Jun 2017 18:00, "insideOven": false, "SuppliesName": 带上清洁用品]]

【问题讨论】:

ios 中没有桌面。所以我想答案是,你不能。 @dasdom 好吧,我可以创建一个到桌面的路径,然后使用write(toFile:atomically:) 将字符串从 Xcode 写入桌面。它有效,但我不知道如何对数组中的元素进行排序。基本上,上面的函数接受一个字符串并将其写入路径。如何获取字典数组,将其转换为字符串,然后将其以有序列表的形式写入桌面? from Xcode to Desktop Xcode 只是代码编辑器,它不是你的应用程序。如果您能够从 您的应用 写入 Mac 桌面,那么这意味着您的应用不是 iOS 应用,而是 macOS 应用。 // 请解释并提供更多细节。 @EricAya 即使部署目标是 Iphone,我也不打算在 AppStore 中托管这个应用程序,这是为了我自己的测试目的。 imgur.com/a/HJr7H 现在,我知道将这个应用程序发布到 AppStore,我将无法将任何内容发送到本地路径,例如桌面。我想在 Xcode 中做的是,当在模拟器中按下按钮时,将此数组 arrayOfDictionary 中的数据发送到位于桌面的文件中。数据应按照我上面的问题进行格式化和排序。 你没听懂我说的,你对一些事情感到困惑。我会试着用几句话来解释。仔细听。 ;) 1-停止说“in Xcode”或“from Xcode”,这是没有意义的。 Xcode 只是您创建应用程序的代码编辑器,它不是应用程序。 2- 从 app 编译后,您可以写入本地存储。如果是 iOS 应用程序,您可以在手机中写入。如果是 macOS 应用程序,您可以在 Mac 中编写。这与 Xcode 或 App Store 无关。 3-您无法从 iOS 应用程序访问您的 Mac 桌面。至少,不只是那样(你需要网络访问)。 【参考方案1】:

如果您只想以“有序/可读”的格式输出您的字典数组,您可以使用这个:

if let orderedKeys = finalDictionary.first?.keys 

    var outputString = ""
    var i = 1

    for d in finalDictionary 
        outputString += "Booking \(i):\n"
        for k in orderedKeys 
            outputString += k + ": " + (d[k] ?? "(no value)") + "\n"
        
        outputString += "\n"
        i += 1
    

    print(outputString)
    // or, write outputString to a text file


注意:这只是快速代码...不一定是最佳的或 100% 无错误,并假设所有记录具有相同的键。更像是“这是一个前进的方向”有点意思:)

编辑:如果字典可能有可变的键集,您可以这样做:

var outputString = ""
var i = 1
for d in finalDictionary 
    outputString += "Booking \(i):\n"
    for k in d.keys 
        outputString += k + ": " + (d[k] ?? "(no value)") + "\n"
    
    outputString += "\n"
    i += 1


print(outputString)

编辑 2: 可能有点“更快捷”的方式:

outputString = ""
i = 1

finalDictionary.forEach 
    outputString += "Booking \(i):\n"
    $0.forEach  outputString += "\($0): \($1)\n" 
    outputString += "\n"
    i += 1


print(outputString)

因为字典是无序的,你可能会得到:

Booking 1:
EmailAddress: johnmm@gmail.com
PhoneNumber: 94949392
FullName: John
.
Booking 2:
SomeOtherKey: Some Value
FullName: Dave
EmailAddress: dave@gmail.com
.
Booking 3:
FullName: Chris
PhoneNumber: 202583963
SomeOtherKey: Some Other Value
EmailAddress: chris@gmail.com

等等。

【讨论】:

感谢您的帮助。但是,字典并不总是具有与用户可以决定写入新数据相同的键。 finalDictionary 是 [String:Any] 类型,在这一行 outputString += k + ": " + (d[k] ?? "(no value)") + "\n" 我收到错误二元运算符 + 不能应用于 String 和 Any 类型的操作数 这是一个基本的 Swift 数据到字符串的东西...尝试用 outputString += "\(k): \(d[k] ?? "(no value)")\n" 替换该行

以上是关于如何在 Xcode 项目中将字典数组写入 .txt 文件的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift/Xcode 中将 JSON 文件转换为数组

Python中将变量按行写入txt文本中

从每个键具有多个值的字典中将数据写入 csv

在 C++ 中将字节写入 ofstream

如何在 Xcode 中将 JSON 数组转换为数组?

如何在ios中将字典的双引号数组解析为json?