У меня есть некоторый код UWP, который я пытаюсь сохранить. Его цель - объединить некоторые текстовые файлы, хранящиеся в структуре каталогов, в один файл XML.
Чтобы сделать это, я предварительно собрал все отдельные строки во всех файлах в структуре директории, используя LINQ:
Imports System.IO
Async Function getAllLines() As IEnumerable(Of String)
Dim _folderPicker As New Windows.Storage.Pickers.FolderPicker()
_folderPicker.FileTypeFilter.Add("*") 'We must add this; it is a known bug
Dim _rootDir As Windows.Storage.StorageFolder = Await _folderPicker.PickSingleFolderAsync()
Dim allDistinctLines As IEnumerable(Of String) = From _file In Directory.GetFiles(_rootDir.Name, "*.txt", SearchOption.AllDirectories) From line In File.ReadAllLines(_file) Where line.Trim().Length > 0 Select line.Trim() Distinct
Return allDistinctLines
End Function
Однако с конца октября, похоже, что-то изменилось в отношении прав доступа к файлам (Источник) . Я вернулся к коду примерно через месяц после того, как он работал, и обнаружил исключение, в котором говорилось, что папка, в которую я ранее мог записывать, была недоступна из-за разрешений. Папка существовала, и я взял папку у сборщика, поэтому подумал, что у меня все хорошо. Ранее, пока я получал файл или папку с помощью средства выбора, я все еще мог использовать функцию System.IO для перечисления, чтения или записи в указанную папку или каталог.
Теперь кажется, что вы должны использовать правильные способности UWP, что хорошо, но я не уверен, как переписать мой запрос LINQ, поскольку методы UWP асинхронны.
Вот что я пробовал:
Async Function getAllLines() As IEnumerable(Of String)
Dim _folderPicker As New Windows.Storage.Pickers.FolderPicker()
_folderPicker.FileTypeFilter.Add("*") 'We must add this; it is a known bug
Dim _rootDir As Windows.Storage.StorageFolder = Await _folderPicker.PickSingleFolderAsync()
Dim queryOptions As New Windows.Storage.Search.QueryOptions()
queryOptions.FileTypeFilter.Add(".txt")
queryOptions.FolderDepth = Windows.Storage.Search.FolderDepth.Deep
Dim allDistinctLines As IEnumerable(Of String) = From _file In Await _rootDir.CreateFileQueryWithOptions(queryOptions).GetFilesAsync() From line In Await Windows.Storage.FileIO.ReadLinesAsync(_file) Where line.Trim().Length > 0 Select line.Trim() Distinct
Return allDistinctLines
End Function
В приведенном выше коде я по крайней мере могу перечислить папку, если закомментирую второе ожидание в LINQ. Проблема в том, что со вторым Await в запросе LINQ я не могу скомпилировать как
'Await' may only be used in a query expression within the first collection expression of the initial 'From' clause or within the collection expression of a 'Join' clause.
Итак, я прочитал предложения Join
, которые, похоже, приравнивают разрозненные данные, что на самом деле не то, что я ищу.
Я прочитал об ошибке в целом, и кажется, что запросы LINQ и асинхронные функции имеют только ограниченную функциональность. Честно говоря, я не знаю достаточно о LINQ, чтобы действительно заявить об этом, но это было мое чувство.
Я нашел этот ответ, который использует Task.WhenAll () для облегчения использования функций LINQ и Async, но я не могу точно понять, как это будет осуществляться на практике.
Как ждать метод в запросе Linq
Итак, я попробовал:
Async Function getAllLines() As IEnumerable(Of String)
Dim _folderPicker As New Windows.Storage.Pickers.FolderPicker()
_folderPicker.FileTypeFilter.Add("*") 'We must add this; it is a known bug
Dim _rootDir As Windows.Storage.StorageFolder = Await _folderPicker.PickSingleFolderAsync()
Dim queryOptions As New Windows.Storage.Search.QueryOptions()
queryOptions.FileTypeFilter.Add(".txt")
queryOptions.FolderDepth = Windows.Storage.Search.FolderDepth.Deep
Dim allFiles As IEnumerable(Of Windows.Storage.StorageFile) = From _file In Await _rootDir.CreateFileQueryWithOptions(queryOptions).GetFilesAsync() Select _file
Dim allDistinctLines As IEnumerable(Of String) = Task.WhenAll(allFiles.Select(Function(_file) Windows.Storage.FileIO.ReadLines.Async(_file).Where(Function(_line) _line.Trim().Length > 0).Distinct()))
Return allDistinctLines
End Function
Но тип возвращаемого значения не тот, он заканчивается каким-то странным IList (Of String) (), что странным образом не работает для меня. Может быть, там есть просто критическое недоразумение.
В любом случае, любая помощь в понимании операций с асинхронными файлами ценится!