- Home /
Error copying PNG
Hi I have an error using WriteAllBytes to copy a png image to a default folder. The file copies it but when opening the image it tells me that the format is not compatible
public class Buscador : MonoBehaviour
{
public Image img;
//public Sprite sp;
public byte[] img2;
string url;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void Buscar()
{
var paths = StandaloneFileBrowser.OpenFilePanel("Title", "", "png", false);
if (paths.Length > 0)
{
StartCoroutine(OutputRoutine(new System.Uri(paths[0]).AbsoluteUri));
var lugar = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"/Trivia/SampleImage.PNG";
var lite= System.Text.Encoding.UTF8.GetBytes(new System.Uri(paths[0]).AbsoluteUri);
System.IO.File.WriteAllBytes(lugar, lite);
}
}
private IEnumerator OutputRoutine(string url)
{
var loader = new WWW(url);
yield return loader;
img.sprite = Sprite.Create(loader.texture, new Rect(0, 0, loader.texture.width, loader.texture.height), new Vector2(0, 0));
}
}
Answer by Bunny83 · Feb 03, 2020 at 06:03 PM
I don't think you really understood what you did there. You never ever actually read a single byte from your source file since you never opened or read the file content.
First of all your coroutine "OutputRoutine" has nothing to do with your "WriteAllBytes". So we can simply get rid of it as it has no relevance on what is written to your file. So lets break down what you did there.
First of all you seem to use some sort of file browser so the user can select one or multiple PNG files. You create a new string variable called "lugar" where you setup an absolute path to a png file in the user's documents folder. This is your target file location.
Now comes the line which makes no sense at all:
var lite = System.Text.Encoding.UTF8.GetBytes(new System.Uri(paths[0]).AbsoluteUri);
It seems you are under the impression that the byte array "lite" would contain the content of the file that is referenced in path[0]
. However that's not true at all. What you do here is that you first create an Uri which is just a wrapper class that represents an Uri. You just pass in the path of the file the user selects. You then grab the AbsoluteUri which just returns you a file Uri. For example this:
string uri = new System.Uri(@"C:\Data\Test.png").AbsoluteUri;
will just give you the string "file:///C:\Data\Test.png"
. Now comes the silly part. You use the UTF8 text encoder to turn the string you pass in into UTF8 bytes. So you just get a byte array of the characters of your Uri text. At no point do you actually perform any kind of file access and reading the content of the file. The byte array would just contain this:
{102, 105, 108, 101, 58, 47, 47, 47, 67, 58, 47, 68, 97, 116, 97, 47, 84, 101, 115, 116, 46, 112, 110, 103}
Which is just the UTF8 encoding of our string above. You then just write that data to your file. Just try opening the file you just created in notepad. What you will see is this
file:///C:\Data\Test.png
Of course not my test path but whatever path you had selected.
If you want to read the file content and copy it to another directory, you have two options. Either read the file content (opening the file, reading all content and closing it or just use System.IO.File.ReadAllBytes) and then use WriteAllBytes with the new file name to write the data to the new location. Or if you don't really care about the data inside your application you can simply copy the file from the source location to the destination location with File.Copy
I would highly suggest to break down long lines into smaller / easier to understand pieces.
string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string destFileName = System.IO.Path.Combine(documentsFolder, @"Trivia/SampleImage.PNG");
byte[] fileContent = System.IO.File.ReadAllBytes(paths[0]);
System.IO.File.WriteAllBytes(destFileName, fileContent);
Note that I used Path.Combine to connect the documents folder path with our subdirectory and file name. This is in general recommeded when you work with file paths. Just adding pieces of a path fragments together can result in some issues depending on if the fragments have or have not leading / trailing slashes. Path.Combine takes care of that. Just always pass fragments without leading backslashes and you're good.
So Path.Combine(@"C:\someFolder", "myFileName.png");
will result in
"C\:someFolder\myFileName.png"