Skip to content

IFormatProvider in TextLoader #126

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ddobric opened this issue May 11, 2018 · 4 comments
Closed

IFormatProvider in TextLoader #126

ddobric opened this issue May 11, 2018 · 4 comments
Assignees

Comments

@ddobric
Copy link

ddobric commented May 11, 2018

Want to know how TextLoader deals with files in different cultures.
For example, if you are running on OS with culture like "de-de" such files might be loaded incorrectly:

CMT,1,1,1267,6.9,CRD,23
CMT,1,1,1267,6.8,CRD,24

With such cultures (none-invariant) would require files formatted in following way (separator = ';')

CMT;1;1;1267;6,9,CRD;23
CMT;1;1;1267;6,8,CRD;23

@veikkoeeva
Copy link
Contributor

veikkoeeva commented May 11, 2018

Cross-referencing since related: #74 and #109. And since this is a real problem, feeding thoughts: https://www.nuget.org/packages?q=CSV.

@veikkoeeva
Copy link
Contributor

veikkoeeva commented May 11, 2018

@ddobric You can see it at

public class TextLoader<TInput> : ILearningPipelineLoader
.

I wonder if it were possible to do something like this

    /// <summary>
    /// A canonical interface for deserializer.
    /// </summary>
    public interface IDeserializer
    {
       /// <summary>
       /// Can this provider stream data.
       /// </summary>
       bool CanStream { get; }

       /// <summary>
       /// Deserializes the given data.
       /// </summary>
       /// <param name="data">The data to be serialized.</param>
       /// <param name="destination">The destination type.</param>
       /// <returns>The deserialized object.</returns>
       object Deserialize(object data, Type destination);

/// <summary>
/// Deserializes the given data from a stream.
/// </summary>
/// <param name="dataStream">The stream from which to serialize.</param>
/// <param name="destination">The destination type.</param>
/// <returns>The deserialized object.</returns>
object Deserialize(Stream dataStream, Type destination);

/// <summary>
/// Deserializes the given data from a text stream.
/// </summary>
/// <param name="reader">The text stream from which to serialize.</param>
/// <param name="destination">The destination type.</param>
/// <returns>The deserialized object.</returns>
object Deserialize(TextReader reader, Type destination);
}

/// <summary>
    /// A default JSON deserializer.
    /// </summary>
    [DebuggerDisplay("CanStream = {CanStream}")]
    public class DefaultJsonDeserializer: IDeserializer
    {
        public JsonSerializer Deserializer { get; }
        public JsonSerializerSettings Settings { get; }
        public bool CanStream { get; } = true;

        public DefaultJsonDeserializer(JsonSerializerSettings settings)
        {
            if(settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            Deserializer = JsonSerializer.Create(settings);
            Settings = settings;
        }

        public object Deserialize(Stream dataStream, Type destination)
        {
            using(var streamReader = new StreamReader(dataStream))
            {
                using(var reader = new JsonTextReader(streamReader))
                {
                    return Deserializer.Deserialize(reader, destination);
                }
            }
        }

        public object Deserialize(object data, Type destination)
        {
            return JsonConvert.DeserializeObject((string)data, destination, Settings);
        }

        public object Deserialize(TextReader reader, Type destination)
        {
            using(var jsonReader = new JsonTextReader(reader))
            {
                return Deserializer.Deserialize(jsonReader, destination);
            }
        }
    }
}

The real case would be more complicated and the interface could support, say IAsyncEnumerable<T>. The intention would be to make canonical interfaces for input (and output) and make concrete implementations in arbitrary ways, users could bring their own (de)serializers. This might be possible in the current system. I don't know what is schema, for instance, in MachineLearning.NET. :)

@sfilipi
Copy link
Member

sfilipi commented Nov 27, 2018

@ddobric you can specify the column separator in the TextLoader, in ML.Net.
The TextLoader's default separator is ' \t'.

The culture does not play a factor.

@codemzs
Copy link
Member

codemzs commented Jun 30, 2019

Please try with the new API in post 1.0 release and let me know if you still see this issue.

@codemzs codemzs closed this as completed Jun 30, 2019
@ghost ghost locked as resolved and limited conversation to collaborators Mar 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants