public static RuntimeCsvRepresentation CsvDeserializeToRuntime(string fileName, char delimiter, HeaderPresence headerPresence = HeaderPresence.HasHeaders) { if (FileManager.IsRelative(fileName)) { throw new NotImplementedException(); //fileName = FileManager.MakeAbsolute(fileName); } //FileManager.ThrowExceptionIfFileDoesntExist(fileName); string extension = FileManager.GetExtension(fileName); #if SILVERLIGHT || XBOX360 || WINDOWS_PHONE Stream fileStream = FileManager.GetStreamForFile(fileName); #else // Creating a filestream then using that enables us to open files that are open by other apps. FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); // StreamReader streamReader = new StreamReader(fileName); #endif RuntimeCsvRepresentation runtimeCsvRepresentation = GetRuntimeCsvRepresentationFromStream(fileStream, headerPresence, true, delimiter); fileStream.Close(); fileStream.Dispose(); #if XBOX360 if (FileManager.IsFileNameInUserFolder(fileName)) { FileManager.DisposeLastStorageContainer(); } #endif return(runtimeCsvRepresentation); }
public static RuntimeCsvRepresentation GetRuntimeCsvRepresentationFromStream(Stream stream, HeaderPresence headerPresence, bool trimEmptyLines, char delimiter) { System.IO.StreamReader streamReader = new StreamReader(stream); RuntimeCsvRepresentation runtimeCsvRepresentation = null; bool hasHeaders = headerPresence == HeaderPresence.HasHeaders; using (CsvReader csv = new CsvReader(streamReader, hasHeaders, delimiter, CsvReader.DefaultQuote, CsvReader.DefaultEscape, CsvReader.DefaultComment, true, CsvReader.DefaultBufferSize)) { csv.SkipsComments = false; runtimeCsvRepresentation = new RuntimeCsvRepresentation(); string[] fileHeaders = csv.GetFieldHeaders(); runtimeCsvRepresentation.Headers = new CsvHeader[fileHeaders.Length]; for (int i = 0; i < fileHeaders.Length; i++) { runtimeCsvRepresentation.Headers[i] = new CsvHeader(fileHeaders[i]); } // use field count instead of header count because there may not be headers int numberOfHeaders = csv.FieldCount; runtimeCsvRepresentation.Records = new List <string[]>(); while (csv.ReadNextRecord()) { string[] newRecord = new string[numberOfHeaders]; bool shouldAddRow = !trimEmptyLines; for (int i = 0; i < numberOfHeaders; i++) { string record = csv[i]; newRecord[i] = record; if (!string.IsNullOrEmpty(record)) { shouldAddRow = true; } } if (shouldAddRow) { runtimeCsvRepresentation.Records.Add(newRecord); } } } // Vic says - not sure how this got here, but it causes a crash! //streamReader.DiscardBufferedData(); streamReader.Close(); streamReader.Dispose(); return(runtimeCsvRepresentation); }
private int ReplaceRow(int i, string[] record, string key, object value) { string keyWithBrackets = "{{" + key + "}}"; if (ContainsStringContain(record, keyWithBrackets)) { if (value is RuntimeCsvRepresentation) { this.Records.RemoveAt(i); RuntimeCsvRepresentation whatToInsert = (RuntimeCsvRepresentation)value; if (whatToInsert.Records != null) { this.Records.InsertRange(i, whatToInsert.Records); i += whatToInsert.Records.Count - 1; // subtract 1 becaue the i++ will add the last one } else { i--; } } else { for (int recordIndex = 0; recordIndex < record.Length; recordIndex++) { if (record[recordIndex].Contains(keyWithBrackets)) { // The user may pass a null // argument. If so, we just // want to remove the {{X}} and // replace it with an empty string. string whatToReplaceWith = ""; if (value != null) { whatToReplaceWith = value.ToString(); } record[recordIndex] = record[recordIndex].Replace(keyWithBrackets, whatToReplaceWith); } } } } return(i); }
public void AppendToThis(RuntimeCsvRepresentation whatToAppend) { // This will not use headers if (whatToAppend.Headers != null && whatToAppend.Headers.Length != 0) { throw new InvalidOperationException("The argument RuntimeCsvRepresentation cannot have headers"); } // Let's make sure there are valid records if (Records == null) { Records = new List <string[]>(); } if (whatToAppend.Records != null) { this.Records.AddRange(whatToAppend.Records); } }
//public void CreateObjectList(Type typeOfElement, IList listToPopulate) //{ // #region If primitive or string // if (typeOfElement.IsPrimitive || typeOfElement == typeof(string)) // { // if (typeOfElement == typeof(string)) // { // listToPopulate.Add(this.Headers[0]); // for (int i = 0; i < this.Records.Count; i++) // { // listToPopulate.Add(this.Records[i][0]); // } // } // else // { // throw new NotImplementedException(); // } // } // #endregion // else if (typeOfElement == typeof(List<string>)) // { // for (int i = 0; i < this.Records.Count; i++) // { // string[] record = Records[i]; // List<string> row = new List<string>(); // listToPopulate.Add(row); // row.AddRange(record); // } // } // else if (typeOfElement == typeof(string[])) // { // for (int i = 0; i < this.Records.Count; i++) // { // listToPopulate.Add(Records[i]); // } // } // #region Not primitive or string (class/struct) // else // { // CreateNonPrimitiveList(typeOfElement, listToPopulate); // } // #endregion //} //public void CreateObjectDictionary<KeyType, ValueType>(Dictionary<KeyType, ValueType> dictionaryToPopulate, string contentManagerName) //{ // Type typeOfElement = typeof(ValueType); // if (typeOfElement.IsPrimitive || typeOfElement == typeof(string)) // { // throw new InvalidOperationException("Can't create dictionaries of primitives or strings because they don't have a key"); // } // else // { // MemberTypeIndexPair[] memberTypeIndexPairs; // PropertyInfo[] propertyInfos; // FieldInfo[] fieldInfos; // GetReflectionInformation(typeOfElement, out memberTypeIndexPairs, out propertyInfos, out fieldInfos); // #region Get the required header which we'll use for the key // CsvHeader csvHeaderForKey = CsvHeader.Empty; // int headerIndex = 0; // foreach (CsvHeader header in Headers) // { // if (header.IsRequired) // { // csvHeaderForKey = header; // break; // } // headerIndex++; // } // if (csvHeaderForKey == CsvHeader.Empty) // { // throw new InvalidOperationException("Could not find a property to use as the key. You need to put (required) after one of the headers to identify it as required."); // } // #endregion // int numberOfColumns = Headers.Length; // object lastElement = null; // bool wasRequiredMissing = false; // for (int row = 0; row < Records.Count; row++) // { // object newElement; // bool newElementFailed; // wasRequiredMissing = TryCreateNewObjectFromRow( // typeOfElement, // contentManagerName, // memberTypeIndexPairs, // propertyInfos, // fieldInfos, // numberOfColumns, // lastElement, // wasRequiredMissing, // row, // out newElement, // out newElementFailed); // if (!newElementFailed && !wasRequiredMissing) // { // KeyType keyToUse = default(KeyType); // if (typeOfElement == typeof(string[])) // { // keyToUse = (KeyType)(((string[])newElement)[headerIndex] as object); // } // else // { // if (csvHeaderForKey.MemberTypes == MemberTypes.Property) // { // keyToUse = LateBinder<ValueType>.Instance.GetProperty<KeyType>((ValueType)newElement, csvHeaderForKey.Name); // } // else // { // keyToUse = LateBinder<ValueType>.Instance.GetField<KeyType>((ValueType)newElement, csvHeaderForKey.Name); // } // } // if (dictionaryToPopulate.ContainsKey(keyToUse)) // { // throw new InvalidOperationException("The key " + keyToUse + // " is already part of the dictionary."); // } // else // { // dictionaryToPopulate.Add(keyToUse, (ValueType)newElement); // } // lastElement = newElement; // } // } // } //} //private void CreateNonPrimitiveList(Type typeOfElement, IList listToPopulate) //{ // MemberTypeIndexPair[] memberTypeIndexPairs; // PropertyInfo[] propertyInfos; // FieldInfo[] fieldInfos; // GetReflectionInformation(typeOfElement, out memberTypeIndexPairs, out propertyInfos, out fieldInfos); // int numberOfColumns = Headers.Length; // object lastElement = null; // bool wasRequiredMissing = false; // for (int row = 0; row < Records.Count; row++) // { // object newElement; // bool newElementFailed; // wasRequiredMissing = TryCreateNewObjectFromRow( // typeOfElement, // contentManagerName, // memberTypeIndexPairs, // propertyInfos, // fieldInfos, // numberOfColumns, // lastElement, // wasRequiredMissing, // row, // out newElement, // out newElementFailed); // if (!newElementFailed && !wasRequiredMissing) // { // listToPopulate.Add(newElement); // lastElement = newElement; // } // } //} //private bool TryCreateNewObjectFromRow(Type typeOfElement, string contentManagerName, MemberTypeIndexPair[] memberTypeIndexPairs, // PropertyInfo[] propertyInfos, FieldInfo[] fieldInfos, int numberOfColumns, object lastElement, bool wasRequiredMissing, int row, out object newElement, out bool newElementFailed) //{ // wasRequiredMissing = false; // newElementFailed = false; // #region Special-case handle string[]. We use these for localization // if (typeOfElement == typeof(string[])) // { // int requiredColumn = -1; // for (int i = 0; i < Headers.Length; i++) // { // if (Headers[i].IsRequired) // { // requiredColumn = i; // break; // } // } // //bool isRequired =; // if (requiredColumn != -1 && string.IsNullOrEmpty(Records[row][requiredColumn])) // { // wasRequiredMissing = true; // newElement = null; // } // else // { // string[] returnObject = new string[numberOfColumns]; // for (int column = 0; column < numberOfColumns; column++) // { // returnObject[column] = Records[row][column]; // } // newElement = returnObject; // } // } // #endregion // else // { // newElement = Activator.CreateInstance(typeOfElement); // for (int column = 0; column < numberOfColumns; column++) // { // if (memberTypeIndexPairs[column].Index != -1) // { // object objectToSetValueOn = newElement; // if (wasRequiredMissing) // { // objectToSetValueOn = lastElement; // } // int columnIndex = memberTypeIndexPairs[column].Index; // bool isRequired = Headers[column].IsRequired; // if (isRequired && string.IsNullOrEmpty(Records[row][column])) // { // wasRequiredMissing = true; // continue; // } // #region If the member is a Property, so set the value obtained from converting the string. // if (memberTypeIndexPairs[column].MemberType == MemberTypes.Property) // { // // Currently requirements for lists are not working on properties. Maybe we need to fix this up sometime // object propertyValueToSet = PropertyValuePair.ConvertStringToType( // Records[row][column], // propertyInfos[memberTypeIndexPairs[column].Index].PropertyType, contentManagerName); // propertyInfos[memberTypeIndexPairs[column].Index].SetValue( // objectToSetValueOn, // propertyValueToSet, // null); // } // #endregion // #region Else, it's a Field, so set the value obtained from converting the string. // else if (memberTypeIndexPairs[column].MemberType == MemberTypes.Field) // { // //try // { // FieldInfo fieldInfo; // bool isList; // object valueToSet; // GetFieldValueToSet(contentManagerName, fieldInfos, row, column, columnIndex, out fieldInfo, out isList, out valueToSet); // if (isList) // { // // Check to see if the list is null. // // If so, create it. We want to make the // // list even if we're not going to add anything // // to it. Maybe we'll change this in the future // // to improve memory usage? // object objectToCallOn = fieldInfo.GetValue(objectToSetValueOn); // if (objectToCallOn == null) // { // objectToCallOn = Activator.CreateInstance(fieldInfo.FieldType); // fieldInfo.SetValue(objectToSetValueOn, objectToCallOn); // } // if (valueToSet != null) // { // MethodInfo methodInfo = fieldInfo.FieldType.GetMethod("Add"); // methodInfo.Invoke(objectToCallOn, new object[] { valueToSet }); // } // } // else if (!wasRequiredMissing) // { // fieldInfo.SetValue(objectToSetValueOn, valueToSet); // } // } // // May 5, 2011: // // This code used // // to try/catch and // // just throw away failed // // attempts to instantiate // // a new object. This caused // // debugging problems. I think // // we should be stricter with this // // and let the exception occur so that // // developers can fix any problems related // // to CSV deseiralization. Silent bugs could // // be difficult/annoying to track down. // //catch // //{ // // // don't worry, just skip for now. May want to log errors in the future if this // // // throw-away of exceptions causes difficult debugging. // // newElementFailed = true; // // break; // //} // } // #endregion // } // } // } // return wasRequiredMissing; //} //private void GetFieldValueToSet(string contentManagerName, FieldInfo[] fieldInfos, int row, int column, int columnIndex, out FieldInfo fieldInfo, out bool isList, out object valueToSet) //{ // fieldInfo = fieldInfos[columnIndex]; // isList = fieldInfo.FieldType.Name == "List`1"; // Type typeOfObjectInCell = fieldInfo.FieldType; // if (isList) // { // typeOfObjectInCell = fieldInfo.FieldType.GetGenericArguments()[0]; // } // string cellValue = Records[row][column]; // if (string.IsNullOrEmpty(cellValue)) // { // valueToSet = null; // } // else // { // valueToSet = PropertyValuePair.ConvertStringToType( // Records[row][column], // typeOfObjectInCell, // contentManagerName); // } //} //private void GetReflectionInformation(Type typeOfElement, out MemberTypeIndexPair[] memberTypeIndexPairs, out PropertyInfo[] propertyInfos, out FieldInfo[] fieldInfos) //{ // memberTypeIndexPairs = new MemberTypeIndexPair[Headers.Length]; // propertyInfos = typeOfElement.GetProperties(); // fieldInfos = typeOfElement.GetFields(); // #region Remove whitespace and commas, identify if the types are required. // // The headers may be include spaces to be more "human readable". // // Of course members can't have spaces. Therefore "Max HP" is acceptable // // as a header, but the member might be MaxHP. Therefore, we need to remove // // whitespace. // for (int i = 0; i < Headers.Length; i++) // { // string modifiedHeader = FlatRedBall.Utilities.StringFunctions.RemoveWhitespace(Headers[i].Name); // bool isRequired = false; // if (modifiedHeader.Contains("(")) // { // int openingIndex = modifiedHeader.IndexOf('('); // isRequired = IsHeaderRequired(modifiedHeader); // modifiedHeader = modifiedHeader.Substring(0, openingIndex); // } // Headers[i].Name = modifiedHeader; // Headers[i].IsRequired = isRequired; // } // #endregion // BuildMemberTypeIndexInformation(memberTypeIndexPairs, propertyInfos, fieldInfos); //} #region Public Methods public RuntimeCsvRepresentation Clone() { RuntimeCsvRepresentation toReturn = new RuntimeCsvRepresentation(); if (this.Headers != null) { toReturn.Headers = new CsvHeader[this.Headers.Length]; this.Headers.CopyTo(toReturn.Headers, 0); } toReturn.Records = new List <string[]>(); foreach (string[] record in this.Records) { string[] newRecord = new string[record.Length]; record.CopyTo(newRecord, 0); toReturn.Records.Add(newRecord); } return(toReturn); }
public static RuntimeCsvRepresentation GetRuntimeCsvRepresentationFromEmbeddedResource(Assembly assembly, string location, HeaderPresence headerPresence, char delimiter = ',') { RuntimeCsvRepresentation toReturn = null; using (Stream resourceStream = assembly.GetManifestResourceStream(location)) { if (resourceStream == null) { string messageToShow = "Could not find resource stream for " + location + ". The following names exist: "; foreach (string name in assembly.GetManifestResourceNames()) { messageToShow += "\n" + name; } throw new Exception(messageToShow); } toReturn = GetRuntimeCsvRepresentationFromStream(resourceStream, headerPresence, true, delimiter); } return(toReturn); }