convert file from bytes in swift 4 - ios

Open byte values, that byte contains "textfile"
I have an android code for convert file from bytes values
String root = Environment.getExternalStorageDirectory().getAbsolutePath();
File myDir = new File(root);
File fileWithinMyDir = new File(myDir, filename);
FileOutputStream dest = new FileOutputStream(fileWithinMyDir);
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(dest));
ZipEntry entry = new ZipEntry(filename);
entry.setSize(input.length);
zos.putNextEntry(entry);
zos.write(input);
zos.closeEntry();
zos.close();
but I tried in swift 4
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
.appendingPathComponent("/download.zip")
print(fileURL)
if let outputStream = OutputStream(url: fileURL, append: true)
{
outputStream.open()
let bytesWritten = outputStream.write(bytes, maxLength: 1024)
if bytesWritten < 0
{
print("write failure")
}
outputStream.close().
}
I save to document directory and open the txt file it has following message displayed when open txt file
The document could not be opened.The file isn't in the correct format
how to open that bytes any one help me

Related

URLResourceValues not working for renaming a file

I have to rename some files in a directory in the Documents directory. I'm trying with URLResourceValues:
let fileURLs = try! FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil)
fileURLS.forEach { fileURL in
// calculate newFileName
var resourceValues = URLResourceValues()
resourceValues.name = newFilename
var mutableFileURL = fileURL
try! mutableFileURL.setResourceValues(resourceValues)
}
After setting resourceValues.name I see this in the console...
key NSMutableString "NSURLNameKey" 0x00000001e7a8a368
value NSString "newName.jpg" 0x0000000283f61fe0
So that part is working. The try! completes without crashing so there were no errors thrown. But mutableFileURL is unchanged. It's got the old name, not the new name.
I see in the docs that setting read-only properties or setting properties not supported will be ignored and will not throw an error. But in my research I see this approach used commonly for renaming files. And I don't think it's a write access thing because if I use the old way it works fine:
try! FileManager.default.moveItem(at: fileURL, to: newFileURL)
What could I be missing here?
P.S. app targets iOS 14, running on a real device running iOS 16.1
You have not shown how you know things didn't work. But you say:
But mutableFileURL is unchanged
Your code isn't supposed to change mutableFileURL. If you're looking at mutableFileURL to see what happened, that's the problem.
The URL here is just a pointer to the file on disk. That's the whole point of the setResourceValues approach. Your code changes the name of the file on disk (and mutableFileURL, the pointer, is now invalid and should just be thrown away).
If you re-fetch the contents of the documents directory, you'll see that your code worked just fine.
Complete example, showing both what I think you are doing and how to do this correctly:
// --- create the file ---
let fm = FileManager.default
let docsurl = try fm.url(
for: .documentDirectory, in: .userDomainMask,
appropriateFor: nil, create: false
)
let newurl = docsurl.appending(path: "howdy.txt")
try "howdy".write(to: newurl, atomically: true, encoding: .utf8)
let arr = try fm.contentsOfDirectory(
at: docsurl, includingPropertiesForKeys: nil
)
arr.forEach { print($0.lastPathComponent) }
// howdy.txt
// --- rename the file ---
var values = URLResourceValues()
values.name = "hello.txt"
var mutableurl = newurl
try mutableurl.setResourceValues(values)
// --- how did we do? this is _not_ the way:
print(mutableurl)
// file:///.../Documents/howdy.txt
// --- how did we do? this _is_ the way
let arr2 = try fm.contentsOfDirectory(
at: docsurl, includingPropertiesForKeys: nil
)
arr2.forEach { print($0.lastPathComponent) }
// hello.txt

Incorrect write EXIF metadata to image

I try put few exif parameters to image, but only few of them are visible.
When check information about exifDictionary all parametras has a value
[1]: https://i.stack.imgur.com/4OirK.png
But when check this file in exiftool, BodySerialNumber are valid, FileSource is incorrect value, and DateTimeOriginal is not visible, really don't understand what's going on
[2]: https://i.stack.imgur.com/mf4l4.png
This is my code, where i try to save meta to file
static func encodeImage(at url: URL, file: File, completionHandler: ((URL?) -> Void)?) {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
let filePath = documentsDirectory.appendingPathComponent("\(UUID().uuidString)\(file.fileExtension ?? ".jpg")")
guard let data = NSData(contentsOf: url),
let src = CGImageSourceCreateWithData(data, nil),
let uti = CGImageSourceGetType(src),
let cfPath = CFURLCreateWithFileSystemPath(nil, filePath.path as CFString, CFURLPathStyle.cfurlposixPathStyle, false),
let dest = CGImageDestinationCreateWithURL(cfPath, uti, 1, nil)
else {
completionHandler?(nil)
return
}
let exifProperties = [
kCGImagePropertyExifBodySerialNumber as String: file.device ?? "0",
kCGImagePropertyExifFileSource as String: file.deviceUrl ?? file.path,
kCGImagePropertyExifDateTimeOriginal as String: "\(file.createdAt.milliseconds)"
] as CFDictionary
let exifDictionary = [
kCGImagePropertyExifDictionary as String: exifProperties
] as CFDictionary
CGImageDestinationAddImageFromSource(dest, src, .zero, exifDictionary)
if CGImageDestinationFinalize(dest) {
completionHandler?(filePath)
} else {
completionHandler?(nil)
}
}
How can I fix it ?
Community wiki
The main problem because in Java / Kotlin, they can programatically write what they want in meta keys, maybe they use another version of exif, I really don't know about it, but in Swift you can use special format to key. All keys described in https://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html
And when I try to write String in kCGImagePropertyExifFileSource field I have 0, because this field must outcome integer value 1 ... 3
The same problem with kCGImagePropertyExifDateTimeOriginal here not only a String must be written, but also a special format YYYY: MM: DD HH: MM: SS, other formats cannot be written into this field !!!
What I mean, read about field formats and types!)

How to store data from an UnsafeMutablePointer in the iOS file system

I am reading data from an MFi external device into a buffer using a 3rd party SDK "sessionController". See below:
let handle: UInt64 = self.sessionController.openFile(file.path, mode: openMode)
if handle == 0 {
//Error
return
}
let c: UInt64 = file.size
var bytesArray: [UInt8] = [UInt8](fileData)
let bufferPointer: UnsafeMutablePointer<UInt8> = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(c))
bufferPointer.initialize(repeating: 0, count: Int(c))
defer {
bufferPointer.deinitialize(count: Int(c))
bufferPointer.deallocate()
}
var sum: UInt32 = 0
let singleSize: UInt32 = 8 << 20
while sum < c {
let read = self.sessionController.readFile(handle, data: bufferPointer, len: singleSize)
if read == 0 {
//There was an error
return
}
sum += read
}
let newPointer : UnsafeRawPointer = UnsafeRawPointer(bufferPointer)
fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("test.MOV")
fileData = Data(bytes: newPointer, count: Int(c))
try! fileData.write(to: fileURL)
//Now use this fileURL to watch video in an AVPlayer...
//AVPlayer(init: fileURL)
For some reason the data stored at the fileURL becomes corrupted (I think) and I am unable to play the video file. I think I am not doing something correctly with Unsafe Swift but I am not sure what. How can I make sure that I have properly read the data from the device into memory, and then taken that data from memory and stored it on the hard drive at the fileURL? What am I doing wrong here? The video will not play in AVPlayer given the fileURL.
The main error is here:
let read = self.sessionController.readFile(handle, data: bufferPointer, len: singleSize)
If you read in multiple chunks then the second and all subsequent reads will overwrite the data read previously. So that should probably be
let read = self.sessionController.readFile(handle, data: bufferPointer + sum, len: singleSize)
Note also that the file size is defined as UInt64, but the variable sum (which holds the total number of bytes read so far) is an UInt32. This will lead to problems if there is more than 4GB data.
But generally I would avoid to read the complete data into a memory buffer. You already read in chunks, so you can write the data immediately to the destination file. Here is how that could look like:
// Output file:
let fileURL = ...
let fileHandle = try FileHandle(forWritingTo: fileURL)
defer { fileHandle.closeFile() }
// Buffer:
let bufferSize = 1024 * 1024 // Choose some buffer size
var buffer = Data(count: bufferSize)
// Read/write loop:
let fileSize: UInt64 = file.size
var remainingToRead = fileSize
while remainingToRead > 0 {
let read = buffer.withUnsafeMutableBytes { bufferPointer in
self.sessionController.readFile(handle, data: bufferPointer, len: UInt32(min(remainingToRead, UInt64(bufferSize))))
}
if read == 0 {
return // Read error
}
remainingToRead -= UInt64(read)
fileHandle.write(buffer)
}
Note also that the data is read directly into a Data value, instead of reading it into allocated memory and then copying it to another Data.

File name that saved in document directory have space character

I want to download video file and save it in the document directory but when i try show that downloaded video, i can't create URL of that file.
i'm using this code for create path for save file. my file name have spacing : (mobileslider video.mp4), and i want to save this video with own name but i can't create url path that contain space. how can solve this problem?
if let url = URL(string:videoURL){
showVideoFromNib(nibURL:url)
}
when i try to remove space from videoURL, showVideoFromNib method called but don't show the video. and when use orginal url, showVideoFromNib method didn't call.
Edit 1:
i change destination path from :
let destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory)
to :
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
let pathComponent = "pack\(self.packID)-\(selectRow + 1).mp4"
let directoryURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let folderPath: URL = directoryURL.appendingPathComponent("Downloads", isDirectory: true)
let fileURL: URL = folderPath.appendingPathComponent(pathComponent)
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}
now i can create URL and my show video method call but video don't show.
this is my new sample path:
/Users/MyUser/Library/Developer/CoreSimulator/Devices/2C2B6A39-5426-4E2C-B25A-CF64817AF26F/data/Containers/Data/Application/5A1BB109-D452-4F03-8820-EE1120E07C3D/Documents/Downloads/pack7-2.mp4
this file exist in this path but video player don't show this.
I solve problem. i'm using
let path = destinationUrl.absoluteString
instead of
let path = destinationUrl.path

Writing: Operation not permitted issue while working pdf

i am working on PDF File to read and write using Core Text .
Below code is to draw content on the PDF file .
let fileName = "pdffilename.pdf"
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0] as NSString
let pathForPDF = documentsDirectory.stringByAppendingString(fileName)
UIGraphicsBeginPDFContextToFile(pathForPDF, CGRectZero, nil)
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0,612,792), nil)
pagedataforPortaits()
UIGraphicsEndPDFContext()
This Code is working absolutely fine of simulator but when i am using a real device i am getting an Error
<Error>: CGDataConsumerCreateWithFilename: failed to open `/var/mobile/Containers/Data/Application/CADA69EB-8879-45EE-BBE0-477AC810BB86/Documentspdffilename.pdf' for writing: Operation not permitted.
deflateEnd: error -3: (null).
deflateEnd: error -3: (null).
<Error>: CGPDFContextCreate: failed to create PDF context delegate.
Any Suggestions ??
The path string needs a "/" separator between the documents directory and file name.
Swift 5.1:
let fileName = "pdffilename.pdf"
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let pathForPDF = documentsDirectory + "/" + fileName

Resources