توی پست قبلی درباره پشتیبان گیری از دیتابیس محلی حرف زدیم حالا میخوایم فایل csv که آپلود کردیمو و دانلود کنیم و محتویاتشو انتقال بدیم به دیتابیسمون.بریم شروع کنیم.
پیش فرض ما تو این سولوشن استفاده از room و retrofit هست.
قبل از همه چیز این خط رو به فایل build.gradle پروژه اضافه کنید و پروژه رو sync کنید
implementation ("com.opencsv:opencsv:5.5.2")
مثلا ریکوست من این شکلیه:
@GET("backup/downloadDb") suspend fun downloadDatabase( @Header("Authorization") token: String? ): Response<ResponseBody>
یه توکن Authorization توی هدر فرستادم و یک جواب گرفتم از نوع ResponseBody
try {
val token = "your token"
val response = retrofitService.downloadDatabase( token = token)
if (response.isSuccessful) {
response.body()?.let { body ->
val success = saveFile(body)
if (success) {
val filePath = getCsvFilePath()
importCsvToDatabase(filePath)
}
}
}else {
// مدیریت پاسخ ناموفق
}
}catch (e: Exception) {
e.printStackTrace()
}
خب تو این قسمت به ترتیب کارای زیر رو انجام دادیم
حالا بریم سراغ بقیش.
fun saveFile(body: ResponseBody): Boolean { return try { val file = File(context.filesDir, "downloaded_file.csv") var inputStream: InputStream? = null var outputStream: FileOutputStream? = null try { inputStream = body.byteStream() outputStream = FileOutputStream(file) val buffer = ByteArray(4096) var bytesRead: Int while (inputStream.read(buffer).also { bytesRead = it } != -1) { outputStream.write(buffer, 0, bytesRead) } outputStream.flush() true } finally { inputStream?.close() outputStream?.close() } } catch (e: Exception) { e.printStackTrace() false } }
خب تو این فانکشن فقط به یه توضیح کلی اکتفا کنم اونم اینکه ResponseBody رو دریافت کردیم و اون رو به صورت استریم تو حافظه دستگاه نوشتیمش و بعد در صورتی که عملیات موفق باشه یه مقدار true برمیگردونیم.
fun importCsvToDatabase(csvFilePath:String) { val csvFile=File(csvFilePath) val csvReader = CSVReader(FileReader(csvFile)) val users= mutableListOf<UserEntity>() csvReader.use { reader -> reader.readNext() // خواندن عنوان ستونها var nextLine: Array<String>? while (reader.readNext().also { nextLine = it } != null) { // فرض کنید ستونهای CSV با فیلدهای کلاس Userتطابق دارند val user= User( id = nextLine!![0].toInt(), name = nextLine!![1], phone=nextLine!![2] ) users.add(user) } } yourDao.insertAllUsers(users) }
خب تو این فاکشن با استفاده از کتابخانه ای که implement کردیم فایل csv رو میخونیم و تو حلقه while برای هر ردیف یک آبجکت user میسازیم و اون رو به یک لیست اضافه میکنیم در آخر هم همه لیستمون رو با فانکشنی که تو کلاس dao خودمون داریم ، insert می کنیم توی تیبل user :
@Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertAllUsers(users: List<UserEntity>)
نکته: بهتره یک مدل domain بسازیم که مجزای از entity ما باشه و اول csv رو به مدل domain تبدیل کنیم بعد اون رو مپ کنیم به entity که مربوط به مباحث clean architecture میشه . ولی من تو اینجا مستقیما از entity استفاده کردم .
امیدوارم مفید بوده باشه . ممنون که این مطلب رو مطالعه کردین :)