Repository: geopandas/geopandas

Issue:
BUG: Unable to open files with fiona where filepath contains a # character
#### Code Sample, a copy-pastable example

```python
import geopandas as gpd
path = 'file:///dropbox/#02 Datastore/sample.shp'
gpd.io.util._parse_uri(path)
```

returns 

`('/dropbox/', '', 'file')`

#### Problem description

Any filepath being opened with fiona via gpd.read_file is parsed through vsi_path() in order to: 
```python
# Opening a file via URL or file-like-object above automatically detects a
# zipped file. In order to match that behavior, attempt to add a zip scheme
# if missing.
```

Which then passes through parseurl which splits on #s and drops part of my file path
#### Expected Output
`(/dropbox/#02 Datastore/sample.shp','', 'file')`

#### Suggested solution idea?

https://github.com/geopandas/geopandas/blob/5186e69d9b81b2bd73fce1d85f3852971d227f8e/geopandas/io/util.py#L27

Could also collect fragments from urlparse and join it to the URI 



Discussion:
Thanks for the report @scazz010, I can replicate this. Also seems to be an issue writing such files. Hopefully pretty straightforward to resolve.

Resolving patch:
diff --git a/geopandas/io/file.py b/geopandas/io/file.py
--- a/geopandas/io/file.py
+++ b/geopandas/io/file.py
@@ -66,11 +66,13 @@ def _import_fiona():
 
 pyogrio = None
 pyogrio_import_error = None
+PYOGRIO_GE_081 = False
 
 
 def _import_pyogrio():
     global pyogrio
     global pyogrio_import_error
+    global PYOGRIO_GE_081
 
     if pyogrio is None:
         try:
@@ -79,6 +81,10 @@ def _import_pyogrio():
         except ImportError as err:
             pyogrio = False
             pyogrio_import_error = str(err)
+        else:
+            PYOGRIO_GE_081 = Version(
+                Version(pyogrio.__version__).base_version
+            ) >= Version("0.8.1")
 
 
 def _check_fiona(func):
diff --git a/geopandas/io/util.py b/geopandas/io/util.py
--- a/geopandas/io/util.py
+++ b/geopandas/io/util.py
@@ -69,7 +69,7 @@ def _parse_uri(path: str):
     scheme : str
         URI scheme such as "https" or "zip+s3".
     """
-    parts = urlparse(path)
+    parts = urlparse(path, allow_fragments=False)
 
     # if the scheme is not one of GDAL's supported schemes, return raw path
     if parts.scheme and not all(p in SCHEMES for p in parts.scheme.split("+")):


Test patch:
diff --git a/geopandas/io/tests/test_file.py b/geopandas/io/tests/test_file.py
--- a/geopandas/io/tests/test_file.py
+++ b/geopandas/io/tests/test_file.py
@@ -2,6 +2,7 @@
 import io
 import os
 import pathlib
+import shutil
 import tempfile
 from collections import OrderedDict
 
@@ -17,7 +18,7 @@
 import geopandas
 from geopandas import GeoDataFrame, read_file
 from geopandas._compat import PANDAS_GE_20, HAS_PYPROJ
-from geopandas.io.file import _detect_driver, _EXTENSION_TO_DRIVER
+from geopandas.io.file import _detect_driver, _EXTENSION_TO_DRIVER, PYOGRIO_GE_081
 from geopandas.testing import assert_geodataframe_equal, assert_geoseries_equal
 from geopandas.tests.util import PACKAGE_DIR, validate_boro_df
 
@@ -694,6 +695,16 @@ def test_allow_legacy_gdal_path(engine, nybb_filename):
     assert isinstance(gdf, geopandas.GeoDataFrame)
 
 
+@pytest.mark.skipif(not PYOGRIO_GE_081, reason="bug fixed in pyogrio 0.8.1")
+def test_read_file_with_hash_in_path(engine, nybb_filename, tmp_path):
+    folder_with_hash = tmp_path / "path with # present"
+    folder_with_hash.mkdir(exist_ok=True, parents=True)
+    read_path = folder_with_hash / "nybb.zip"
+    shutil.copy(nybb_filename[6:], read_path)
+    gdf = read_file(read_path, engine=engine)
+    assert isinstance(gdf, geopandas.GeoDataFrame)
+
+
 def test_read_file_bbox_tuple(df_nybb, engine, nybb_filename):
     bbox = (
         1031051.7879884212,