I have an issue with Files.
I am doing an image importer so clients put their files on an FTP server and then they can import it in the application.
During the import process I copy the file in the FTP Folder to another folder with File.copy
public List<Visuel> ImportVisuel(int galerieId, string[] images)
{
Galerie targetGalerie = MemoryCache.GetGaleriById(galerieId);
List<FormatImage> listeFormats = MemoryCache.FormatImageToList();
int i = 0;
List<Visuel> visuelAddList = new List<Visuel>();
List<Visuel> visuelUpdateList = new List<Visuel>();
List<Visuel> returnList = new List<Visuel>();
foreach (string item in images)
{
i++;
Progress.ImportProgress[Progress.Guid] = "Image " + i + " sur " + images.Count() + " importées";
string extension = Path.GetExtension(item);
string fileName = Path.GetFileName(item);
string originalPath = HttpContext.Current.Request.PhysicalApplicationPath + "Uploads\\";
string destinationPath = HttpContext.Current.Server.MapPath("~/Images/Catalogue") + "\\";
Visuel importImage = MemoryCache.GetVisuelByFilName(fileName);
bool update = true;
if (importImage == null) { importImage = new Visuel(); update = false; }
Size imageSize = importImage.GetJpegImageSize(originalPath + fileName);
FormatImage format = listeFormats.Where(f => f.width == imageSize.Width && f.height == imageSize.Height).FirstOrDefault();
string saveFileName = Guid.NewGuid() + extension;
File.Copy(originalPath + fileName, destinationPath + saveFileName);
if (format != null)
{
importImage.format = format;
switch (format.key)
{
case "Catalogue":
importImage.fileName = saveFileName;
importImage.originalFileName = fileName;
importImage.dossier = targetGalerie;
importImage.dossier_id = targetGalerie.id;
importImage.filePath = "Images/Catalogue/";
importImage.largeur = imageSize.Width;
importImage.hauteur = imageSize.Height;
importImage.isRoot = true;
if (update == false) { MemoryCache.Add(ref importImage); returnList.Add(importImage); }
if (update == true) visuelUpdateList.Add(importImage);
foreach (FormatImage f in listeFormats)
{
if (f.key.StartsWith("Catalogue_"))
{
string[] keys = f.key.Split('_');
string destinationFileName = saveFileName.Insert(saveFileName.IndexOf('.'), "-" + keys[1].ToString());
string destinationFileNameDeclinaison = destinationPath + destinationFileName;
VisuelResizer declinaison = new VisuelResizer();
declinaison.Save(originalPath + fileName, f.width, f.height, 1000, destinationFileNameDeclinaison);
Visuel visuel = MemoryCache.GetVisuelByFilName(fileName.Insert(fileName.IndexOf('.'), "-" + keys[1].ToString()));
update = true;
if (visuel == null) { visuel = new Visuel(); update = false; }
visuel.parent = importImage;
visuel.filePath = "Images/Catalogue/";
visuel.fileName = destinationFileName;
visuel.originalFileName = string.Empty;
visuel.format = f;
//visuel.dossier = targetGalerie; On s'en fout pour les déclinaisons
visuel.largeur = f.width;
visuel.hauteur = f.height;
if (update == false)
{
visuelAddList.Add(visuel);
}
else
{
visuelUpdateList.Add(visuel);
}
//importImage.declinaisons.Add(visuel);
}
}
break;
}
}
}
MemoryCache.Add(ref visuelAddList);
// FONCTION à implémenter
MemoryCache.Update(ref visuelUpdateList);
return returnList;
}
After some processes on the copy (the original file is no more used)
the client have a pop-up asking him if he wants to delete the original files in the ftp folder.
If he clicks on Ok another method is called on the same controller
and this method use
public void DeleteImageFile(string[] files)
{
for (int i = 0; i < files.Length; i++)
{
File.Delete(HttpContext.Current.Request.PhysicalApplicationPath + files[i].Replace(#"/", #"\"));
}
}
This method works fine and really delete the good files when I use it in other context.
But here I have an error message:
Process can't acces to file ... because it's used by another process.
Someone have an idea?
Thank you.
Here's the screenshot of Process Explorer
There are couple of thing you can do here.
1) If you can repro it, you can use Process Explorer at that moment and see which process is locking the file and if the process is ur process then making sure that you close the file handle after your work is done.
2) Use try/catch around the delete statement and retry after few seconds to see if the file handle was released.
3) If you can do it offline you can put in some queue and do the deletion on it later on.
You solve this by using c# locks. Just embed your code inside a lock statement and your threads will be safe and wait each other to complete processing.
I found the solution:
in my import method, there a call to that method
public void Save(string originalFile, int maxWidth, int maxHeight, int quality, string filePath)
{
Bitmap image = new Bitmap(originalFile);
Save(ref image, maxWidth, maxHeight, quality, filePath);
}
The bitmap maintains the file opened blocking delete.
just added
image.Dispose();
in the methos and it work fine.
Thank you for your help, and thank you for process explorer. Very useful tool
Related
I've got a windows service that I have to modify. Current code is this:
public IRecord2 GetRecord(string name)
{
string path = Path.Combine(this.DirectoryPath, name);
if (!File.Exists(path))
return null;
byte[] contents;
lock (locker) {
using(FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, bufferSize:4096, useAsync:true)) //WHERE THE PROBLEM IS OCCURRING
{
using (BinaryReader br = new BinaryReader(fs))
{
contents = br.ReadBytes((int)fs.Length);
br.Close(); //unnecessary but threw it in just to be sure
fs.Close(); //unnecessary but threw it in just to be sure
}
}
}
return new Record2()
{
Name = name,
Contents = contents
};
}
Code that calls the function:
public void Process(string pickupFileName)
{
string uniqueId = DateTime.Now.ToString("(yyyy-MM-dd_HH-mm-ss)");
string exportFileName = Path.GetFileNameWithoutExtension(pickupFileName) + "_" + uniqueId + ".csv";
string archiveFileName = Path.GetFileNameWithoutExtension(pickupFileName) + "_" + uniqueId + Path.GetExtension(pickupFileName);
string unprocessedFileName = Path.GetFileNameWithoutExtension(pickupFileName) + "_" + uniqueId + Path.GetExtension(pickupFileName);
try
{
_logger.LogInfo(String.Format("Processing lockbox file '{0}'", pickupFileName));
IRecord2 record = _pickup.GetRecord(pickupFileName);
if (record == null)
return;
_archive.AddOrUpdate(new Record2() { Name = archiveFileName, Contents = record.Contents });
string pickupFileContents = UTF8Encoding.UTF8.GetString(record.Contents);
IBai2Document document = Bai2Document.CreateFromString(pickupFileContents);
StringBuilder sb = Export(document);
_export.AddOrUpdate(new Record2() { Name = exportFileName, Contents = Encoding.ASCII.GetBytes(sb.ToString()) });
_pickup.Delete(pickupFileName);
}
catch(Exception ex)
{
throw ex;
}
}
Function that calls Process:
public void Process()
{
foreach (ConfigFolderPath configFolderPath in _configSettings.ConfigFolderPaths)
{
IRecordRepository pickup = new FileRepository(configFolderPath.PickupFolderPath);
IRecordRepository export = new FileRepository(configFolderPath.ExportFolderPath);
IRecordRepository archive = new FileRepository(configFolderPath.ArchiveFolderPath);
IRecordRepository unprocessed = new FileRepository(configFolderPath.UnprocessedFolderPath);
Converter converter = new Converter(Logger,pickup, export, archive, unprocessed);
foreach (string fileName in pickup.GetNames())
{
if (_configSettings.SupportedFileExtensions.Count > 0 && !_configSettings.SupportedFileExtensions.Any(extension => extension.ToLower() == Path.GetExtension(fileName).ToLower()))
continue;
Action action = () => converter.Process(fileName);
_queue.TryEnqueue(action, new WorkTicket() { Description = String.Format("Processing '{0}'", fileName), SequentialExecutionGroup = fileName });
}
}
}
When 1 file is sent to the service, it processes and reads the file correctly. However, if two files are sent (difference of 3 minutes), the first file will process correctly, but the second will give me "System.IO.IOException: The process cannot access the file "filename" because it is being used by another process.
Is the solution to use a mutex as per https://stackoverflow.com/a/29941548/4263285 or is there a better solution to solve this?
Edit: More context:
Service is constantly running - as soon as files are dropped into a folder, it begins the process.
get the file data (function up above)
take the data, transform it, and put it into a different file
Delete the original file from the one up above
rinse and repeat if more files
if one file is placed in the folder, it works correctly.
if two files are placed in the folder, it breaks on the second file
if service is stopped and restarted, it works again
In your code add ".Close()" here, at the end of the line :
using(FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, bufferSize:4096, useAsync:true).Close())
I have an existing program that does some processing a .pdf file and splitting it into multiple .pdf files based on looking for barcodes on the pages.
The program uses ImageMagick and C#.
I want to change it from outputting pdfs to outputting tifs. Look for the comment in the code below for where I would guess the change would be made.
I included the ImageMagick tag because someone might offer a commandline option that someone else can help me convert to C#.
private void BurstPdf(string bigPdfName, string targetfolder)
{
bool outputPdf = true; // change to false to output tif.
string outputExtension = "";
var settings = new MagickReadSettings { Density = new Density(200) };
string barcodePng = Path.Combine("C:\TEMP", "tmp.png");
using (MagickImageCollection pdfPageCollection = new MagickImageCollection())
{
pdfPageCollection.Read(bigPdfName, settings);
int inputPageCount = 0;
int outputPageCount = 0;
int outputFileCount = 0;
MagickImageCollection resultCollection = new MagickImageCollection();
string barcode = "";
string resultName = "";
IBarcodeReader reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>();
reader.Options.PossibleFormats.Add(BarcodeFormat.CODE_39);
reader.Options.TryHarder = false;
foreach (MagickImage pdfPage in pdfPageCollection)
{
MagickGeometry barcodeArea = getBarCodeArea(pdfPage);
IMagickImage barcodeImg = pdfPage.Clone();
barcodeImg.ColorType = ColorType.Bilevel;
barcodeImg.Depth = 1;
barcodeImg.Alpha(AlphaOption.Off);
barcodeImg.Crop(barcodeArea);
barcodeImg.Write(barcodePng);
inputPageCount++;
using (var barcodeBitmap = new Bitmap(barcodePng))
{
var result = reader.Decode(barcodeBitmap);
if (result != null)
{
// found a first page because it has bar code.
if (result.BarcodeFormat.ToString() == "CODE_39")
{
if (outputFileCount != 0)
{
// write out previous pages.
if (outputPdf) {
outputExtension = ".pdf";
} else {
// What do I put here to output a g4 compressed tif?
outputExtension = ".tif";
}
resultName = string.Format("{0:D4}", outputFileCount) + "-" + outputPageCount.ToString() + "-" + barcode + outputExtension;
resultCollection.Write(Path.Combine(targetfolder, resultName));
resultCollection = new MagickImageCollection();
}
barcode = standardizePhysicalBarCode(result.Text);
outputFileCount++;
resultCollection.Add(pdfPage);
outputPageCount = 1;
}
else
{
Console.WriteLine("WARNING barcode is not of type CODE_39 so something is wrong. check page " + inputPageCount + " of " + bigPdfName);
if (inputPageCount == 1)
{
throw new Exception("barcode not found on page 1. see " + barcodePng);
}
resultCollection.Add(pdfPage);
outputPageCount++;
}
}
else
{
if (inputPageCount == 1)
{
throw new Exception("barcode not found on page 1. see " + barcodePng);
}
resultCollection.Add(pdfPage);
outputPageCount++;
}
}
if (File.Exists(barcodePng))
{
File.Delete(barcodePng);
}
}
if (resultCollection.Count > 0)
{
if (outputPdf) {
outputExtension = ".pdf";
} else {
// What do I put here to output a g4 compressed tif?
outputExtension = ".tif";
}
resultName = string.Format("{0:D4}", outputFileCount) + "-" + outputPageCount.ToString() + "-" + barcode + outputExtension;
resultCollection.Write(Path.Combine(targetfolder, resultName));
outputFileCount++;
}
}
}
[EDIT] The above code is what I am using (which some untested modifications) to split a .pdf into other .pdfs. I want to know how to modify this code to output tiffs. I put a comment in the code where I think the change would go.
[EDIT] So encouraged by #fmw42 I just ran the code with the .tif extension enabled. Looks like it did convert to a .tif, but the tif is not compressed. I am surprised that IM just configures the output based on the extension name of the file. Handy I guess, but just seems a little loose.
[EDIT] I figured it out. Although counter-intuitive ones sets the compression on the read of the file. I am reading a .pdf but I set the compression to Group for like this:
var settings = new MagickReadSettings { Density = new Density(200), Compression = CompressionMethod.Group4 };
The thing I learned was that simply naming the output file .tif tells IM to output a tif. That is a handy way to do it, but it just seems sloppy.
When we are copying images in one folder to another folder, images are going to copy one by one, then it takes more time when thousands's of images are copying, Is there any Possibility to copy Multiple images at a time? "This is My code"
int avilableCharts = 0;
int unavialableCharts = 0;
string chartid;
int count = 0;
StreamReader rd = new StreamReader(txtFileName.Text);
StreamWriter tw = new StreamWriter("C:\\LogFiles\\SucessfullyMovedImages.txt");
StreamWriter tw1 = new StreamWriter("C:\\LogFiles\\UnavailableImages.txt");
DirectoryInfo dirinfo = new DirectoryInfo(txtSourceFolder.Text);
FileInfo[] file = dirinfo.GetFiles("*.pdf");
while (!rd.EndOfStream)
{
chartid = rd.ReadLine() + ".pdf";
count = count + 1;
worker.ReportProgress(count);
string FName = string.Empty;
if (File.Exists(txtSourceFolder.Text + chartid))
{
File.Copy(txtSourceFolder.Text + chartid , txtDestinationFolder.Text + chartid );
avilableCharts = avilableCharts + 1;
tw.WriteLine(chartid);
}
else
{
unavialableCharts = unavialableCharts + 1;
tw1.WriteLine(chartid);
}
}
tw.Close();
tw1.Close();
MessageBox.Show("Successfully Copied Images are :" + avilableCharts);
MessageBox.Show("Total Unavilable Images are : " + unavialableCharts);
use below code :
public class SimpleFileMove
{
static void Main()
{
string sourceFile = #"C:\Users\Public\public\test.txt";
string destinationFile = #"C:\Users\Public\private\test.txt";
// To move a file or folder to a new location:
System.IO.File.Move(sourceFile, destinationFile);
// To move an entire directory. To programmatically modify or combine
// path strings, use the System.IO.Path class.
System.IO.Directory.Move(#"C:\Users\Public\public\test\", #"C:\Users\Public\private");
}
}
I want to upload an image file and then extract its basic information (author, dimensions, date created, modified, etc) and display it to the user. How can I do it.
A solution or reference to this problem in asp.net c# code would be helpful. But javascript or php would be ok as well.
Check this Link. You will get more Clearance about GetDetailsOf() and its File Properties based on the Win-OS version wise.
If you want to use C# code use below code to get Metadata's:
List<string> arrHeaders = new List<string>();
Shell shell = new ShellClass();
Folder rFolder = shell.NameSpace(_rootPath);
FolderItem rFiles = rFolder.ParseName(filename);
for (int i = 0; i < short.MaxValue; i++)
{
string value = rFolder.GetDetailsOf(rFiles, i).Trim();
arrHeaders.Add(value);
}
C# solution could be found here:
Link1
Link2
Bitmap image = new Bitmap(fileName);
PropertyItem[] propItems = image.PropertyItems;
foreach (PropertyItem item in propItems)
{
Console.WriteLine("iD: 0x" + item.Id.ToString("x"));
}
MSDN Reference
C# Tutorial Reference
try this...
private string doUpload()
{
// Initialize variables
string sSavePath;
sSavePath = "images/";
// Check file size (mustn’t be 0)
HttpPostedFile myFile = FileUpload1.PostedFile;
int nFileLen = myFile.ContentLength;
if (nFileLen == 0)
{
//**************
//lblOutput.Text = "No file was uploaded.";
return null;
}
// Check file extension (must be JPG)
if (System.IO.Path.GetExtension(myFile.FileName).ToLower() != ".jpg")
{
//**************
//lblOutput.Text = "The file must have an extension of JPG";
return null;
}
// Read file into a data stream
byte[] myData = new Byte[nFileLen];
myFile.InputStream.Read(myData, 0, nFileLen);
// Make sure a duplicate file doesn’t exist. If it does, keep on appending an
// incremental numeric until it is unique
string sFilename = System.IO.Path.GetFileName(myFile.FileName);
int file_append = 0;
while (System.IO.File.Exists(Server.MapPath(sSavePath + sFilename)))
{
file_append++;
sFilename = System.IO.Path.GetFileNameWithoutExtension(myFile.FileName)
+ file_append.ToString() + ".jpg";
}
// Save the stream to disk
System.IO.FileStream newFile
= new System.IO.FileStream(Server.MapPath(sSavePath + sFilename),
System.IO.FileMode.Create);
newFile.Write(myData, 0, myData.Length);
newFile.Close();
return sFilename;
}
So I am working on a C# program that takes in a set of delimited text files within a directory and parses out the info within the files (i.e. the file path, file name, associated keywords). And this is what a sample file looks like...
C:\Documents and Settings\workspace\Extracted Items\image2.jpeg;image0;keyword1, keyword2, keyword3, keyword4
C:\Documents and Settings\workspace\Extracted Items\image3.jpeg;image1;keyword1, keyword2, keyword3, keyword4
C:\Documents and Settings\workspace\Extracted Items\image4.jpeg;image2;keyword1, keyword2, keyword3, keyword4
C:\Documents and Settings\workspace\Extracted Items\image5.jpeg;image3;keyword1, keyword2, keyword3, keyword4
Well I was given some code by my partner that does this, but I need to be able to access the list variable, that is populated within one of the methods. This is the code:
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApp
{
public class FileIO
{
private static Boolean isTextFile;
private static Boolean debug;
private static int semiColonLoc1, semiColonLoc2, dblQuoteLoc1;
private static int lineLength, currentTagLength;
private static int numImages;
private static int numFiles;
public static List<Image> lImageSet;
/*
****************************************************
***** CHANGE THIS PATH TO YOUR PROPERTIES FILE *****
****************************************************
*/
private static readonly string propertiesFileDir = "C:/Documents and Settings/properties.properties";
public PropertyKeys getProperties(string propertiesFileDir, PropertyKeys aPropertyKeys)
{
string line;
string directoryKey = "extractedInfoDirectory";
string debugKey = "debug2";
string directory;
Boolean isDirectoryKey;
Boolean isDebugKey;
System.IO.StreamReader file = new System.IO.StreamReader(propertiesFileDir);
while ((line = file.ReadLine()) != null)
{
isDirectoryKey = false;
isDebugKey = false;
// If the current line is a certain length, checks the current line's key
if (line.Length > debugKey.Length)
{
isDebugKey = line.Substring(0, debugKey.Length).Equals(debugKey, StringComparison.Ordinal);
if (line.Length > directoryKey.Length)
{
isDirectoryKey = line.Substring(0, directoryKey.Length).Equals(directoryKey, StringComparison.Ordinal);
}
}
// Checks if the current line's key is the extractedInfoDirectory
if (isDirectoryKey)
{
directory = line.Substring(directoryKey.Length + 1);
aPropertyKeys.setExtractedInfoDir(directory);
}
// Checks if the current line's key is the debug2
else if (isDebugKey)
{
debug = Convert.ToBoolean(line.Substring(debugKey.Length + 1));
aPropertyKeys.setDebug(debug);
}
}
return aPropertyKeys;
}
public void loadFile()
{
string line;
string tempLine;
string fileToRead;
string fileRename;
string imagePath, imageName, imageTags, currentTag;
string extractedInfoDir;
string extension;
string textfile = "txt";
string[] filePaths;
PropertyKeys aPropertyKeys = new PropertyKeys();
// Finds extractedInfoDir and debug values
aPropertyKeys = getProperties(propertiesFileDir, aPropertyKeys);
extractedInfoDir = aPropertyKeys.getExtractedInfoDir();
debug = aPropertyKeys.getDebug();
// Finds all files in the extracted info directory
filePaths = Directory.GetFiles(extractedInfoDir);
numFiles = filePaths.Length;
// For each file in the directory...
for (int n = 0; n < numFiles; n++)
{
int k = filePaths[n].Length;
// Finds extension for the current file
extension = filePaths[n].Substring(k - 3);
// Checks if the current file is .txt
isTextFile = extension.Equals(textfile, StringComparison.Ordinal);
// Only reads file if it is .txt
if (isTextFile == true)
{
fileToRead = filePaths[n];
Console.WriteLine(fileToRead);
System.IO.StreamReader file = new System.IO.StreamReader(fileToRead);
// Reset variables and create a new lImageSet object
lImageSet = new List<Image>();
line = ""; tempLine = ""; imagePath = ""; imageName = ""; imageTags = ""; currentTag = "";
semiColonLoc1 = 0; semiColonLoc2 = 0; dblQuoteLoc1 = 0; lineLength = 0; currentTagLength = 0; numImages = 0;
while ((line = file.ReadLine()) != null)
{
// Creates a new Image object
Image image = new Image();
numImages++;
lineLength = line.Length;
// Finds the image path (first semicolon delimited field)
semiColonLoc1 = line.IndexOf(";");
imagePath = line.Substring(0, semiColonLoc1);
image.setPath(imagePath);
tempLine = line.Substring(semiColonLoc1 + 1);
// Finds the image name (second semicolon delimited field)
semiColonLoc2 = tempLine.IndexOf(";");
imageName = tempLine.Substring(0, semiColonLoc2);
image.setName(imageName);
tempLine = tempLine.Substring(semiColonLoc2 + 1);
// Finds the image tags (third semicolon delimited field)
imageTags = tempLine;
dblQuoteLoc1 = 0;
// Continues to gather tags until there are none left
while (dblQuoteLoc1 != -1)
{
dblQuoteLoc1 = imageTags.IndexOf("\"");
imageTags = imageTags.Substring(dblQuoteLoc1 + 1);
dblQuoteLoc1 = imageTags.IndexOf("\"");
if (dblQuoteLoc1 != -1)
{
// Finds the next image tag (double quote deliminated)
currentTag = imageTags.Substring(0, dblQuoteLoc1);
currentTagLength = currentTag.Length;
// Adds the tag to the current image
image.addTag(currentTag);
image.iNumTags++;
imageTags = imageTags.Substring(dblQuoteLoc1 + 1);
}
}
// Adds the image to the current image set
lImageSet.Add(image);
}
// Prints out information about what information has been stored
if (debug == true)
{
Console.WriteLine("Finished file " + (n + 1) + ": " + filePaths[n]);
for (int i = 0; i < numImages; i++)
{
Console.WriteLine();
Console.WriteLine("***Image " + (i + 1) + "***");
Console.WriteLine("Name: " + lImageSet.ElementAt(i).getName());
Console.WriteLine("Path: " + lImageSet.ElementAt(i).getPath());
Console.WriteLine("Tags: ");
for (int j = 0; j < lImageSet.ElementAt(i).iNumTags; j++)
{
Console.WriteLine(lImageSet.ElementAt(i).lTags.ElementAt(j));
}
}
}
file.Close();
// Changes destination file extension to .tmp
fileRename = fileToRead.Substring(0, fileToRead.Length - 4);
fileRename += ".tmp";
// Changes file extension to .tmp
System.IO.File.Move(fileToRead, fileRename);
}
// Not a text file
else
{
Console.WriteLine("Skipping file (no .txt extension)");
}
}
Console.ReadLine();
}
}
}
However, I don't want to mess with his code too much as he is not here for the time being to fix anything. So I just want to know how to access lImageSet from within his code in another class of mine. I was hoping it would be something like instantiating FileIO with FileIO fo = new FileIO, then doing something like fo.loadFile().lImageSet but that's not the case. Any ideas?
Since lImageSet is static, all you need to do to access it is:
List<image> theList = FileIO.lImageSet;
No instantiated object is necessary to get a reference to that field.
The list is static, so you access it with the name of the class:
List<Image> theList = FileIO.lImageSet
The loadFile method returns void, so you cannot use the dot operator to access anything from it. You'll want to do something like this:
FileIO fo = new FileIO();
fo.loadFile();
List<Image> theImages = FileIO.lImageSet;
It's public -- so from your class, you can just access it as:
FileIO.lImageSet
To get to the values in it, just iterate over it as:
//from FishBasketGordo's answer - load up the fo object
FileIO fo = new FileIO();
fo.loadFile();
foreach(var img in FileIO.lImageSet) {
//do something with each img item in lImageSet here...
}
EDIT: I built upon FishBasketGordo's answer by incorporating his loadFile() call into my sample.
Because lImageSet is static, so you don't need to instantiate FileIO to get it.
Try FileIO.lImageSet